In Python, dunder methods (short for “double underscore”) are those whose names begin and end with two underscores (__
).
These methods are not called directly, but are automatically invoked by the Python interpreter in various situations (such as arithmetic operations, sequence manipulation, and context management).
Also known as magic or special methods
Some of the most common dunder methods are:
Method | Description |
---|---|
__init__ | Initializes a new instance of a class |
__str__ | Returns a string representation of an object, user-friendly |
__repr__ | Returns a string representation of an object, developer-friendly |
__len__ | Returns the length of an object |
__getitem__ | Allows access to elements using indices |
__setitem__ | Allows assigning values to elements using indices |
__delitem__ | Allows deleting elements using indices |
__iter__ | Returns an iterator for the object |
__next__ | Returns the next element from the iterator |
Implementing Dunder Methods
Let’s see how some of these methods are implemented and used in a class in Python.
Method init
The __init__
method is used to initialize the attributes of a class when a new instance is created.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person1 = Person("Alice", 30)
print(person1.name) # Output: Alice
print(person1.age) # Output: 30
Methods str and repr
The __str__
and __repr__
methods return string representations of an object. The main difference is that __str__
is intended for a user-friendly representation, while __repr__
is aimed at developers and should be more detailed.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Person: {self.name}, {self.age} years"
def __repr__(self):
return f"Person('{self.name}', {self.age})"
person1 = Person("Alice", 30)
print(str(person1)) # Output: Person: Alice, 30 years
print(repr(person1)) # Output: Person('Alice', 30)
Method len
The __len__
method is used to return the length of an object.
class Group:
def __init__(self, members):
self.members = members
def __len__(self):
return len(self.members)
group = Group(["Alice", "Bob", "Charlie"])
print(len(group)) # Output: 3
Methods getitem, setitem, and delitem
These methods allow objects of a class to behave like containers (lists, dictionaries, etc.).
class MyList:
def __init__(self):
self.data = []
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value
def __delitem__(self, index):
del self.data[index]
my_list = MyList()
my_list.data = [1, 2, 3, 4, 5]
print(my_list[2]) # Output: 3
my_list[2] = 30
print(my_list[2]) # Output: 30
del my_list[2]
print(my_list.data) # Output: [1, 2, 4, 5]
Methods iter and next
These methods allow objects of a class to be iterable.
class Counter:
def __init__(self, max):
self.max = max
self.counter = 0
def __iter__(self):
return self
def __next__(self):
if self.counter < self.max:
self.counter += 1
return self.counter
else:
raise StopIteration
counter = Counter(5)
for number in counter:
print(number)
Dunder Methods for Arithmetic Operations
In addition to the mentioned methods, Python allows overloading arithmetic operators using dunder methods like __add__
, __sub__
, __mul__
, __truediv__
, among others.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __repr__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(4, 5)
v3 = v1 + v2
print(v3) # Output: Vector(6, 8)