In Python, dunder methods (short for “double underscore”) are those whose names begin and end with two underscores (__
).
These methods are not called directly; instead, they 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, they allow us to define the behavior of basic operations with objects of our classes.
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 accessing elements via indices |
__setitem__ | Allows assigning values to elements via indices |
__delitem__ | Allows deleting elements via indices |
__iter__ | Returns an iterator for the object |
__next__ | Returns the next element from the iterator |
Implementation of 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 the 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 the 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 methods mentioned, 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)