Unlock Python’s Power: 20 Essential Magic Methods Explained with Code
This article introduces twenty commonly used Python magic (dunder) methods, explains their purpose such as object initialization, representation, iteration, arithmetic, and context management, and provides clear code examples for each to help developers apply them in real‑world automation tasks.
Python provides a set of special "magic" methods—also called dunder methods because they begin and end with double underscores—that let developers customize object behavior for creation, representation, comparison, arithmetic, iteration, attribute access, and more. The following sections describe twenty of the most useful magic methods and include concrete code examples that can be directly used in automation scripts or other projects.
__init__(self[, args...])
Object initialization method called when a new instance is created.
class MyClass:
def __init__(self, name):
self.name = name
obj = MyClass("Alice")__str__(self)
Returns a human‑readable string representation of the object.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
p = Point(3, 4)
print(p) # Output: (3, 4)__len__(self)
Defines the behavior of the built‑in len() function for the object.
class MyList:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
my_list = MyList([1, 2, 3, 4, 5])
print(len(my_list)) # Output: 5__getitem__(self, key)
Retrieves the element at the specified index or key.
class MyList:
def __init__(self, items):
self.items = items
def __getitem__(self, index):
return self.items[index]
my_list = MyList([1, 2, 3, 4, 5])
print(my_list[2]) # Output: 3__setitem__(self, key, value)
Assigns a value to the element at the given index or key.
class MyList:
def __init__(self, items):
self.items = items
def __setitem__(self, index, value):
self.items[index] = value
my_list = MyList([1, 2, 3, 4, 5])
my_list[2] = 10
print(my_list.items) # Output: [1, 2, 10, 4, 5]__delitem__(self, key)
Deletes the element at the specified index or key.
class MyList:
def __init__(self, items):
self.items = items
def __delitem__(self, index):
del self.items[index]
my_list = MyList([1, 2, 3, 4, 5])
del my_list[2]
print(my_list.items) # Output: [1, 2, 4, 5]__contains__(self, item)
Implements the in operator to test membership.
class MyList:
def __init__(self, items):
self.items = items
def __contains__(self, item):
return item in self.items
my_list = MyList([1, 2, 3, 4, 5])
print(3 in my_list) # Output: True__iter__(self)
Returns an iterator object, enabling iteration with for loops.
class MyList:
def __init__(self, items):
self.items = items
def __iter__(self):
return iter(self.items)
my_list = MyList([1, 2, 3, 4, 5])
for item in my_list:
print(item) # Outputs: 1 2 3 4 5__next__(self)
Provides the next element of an iterator; used when the object itself is an iterator.
class MyList:
def __init__(self, items):
self.items = items
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.items):
raise StopIteration
value = self.items[self.index]
self.index += 1
return value
my_list = MyList([1, 2, 3, 4, 5])
for item in my_list:
print(item) # Outputs: 1 2 3 4 5__eq__(self, other)
Defines equality comparison between two objects.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
p1 = Point(3, 4)
p2 = Point(3, 4)
print(p1 == p2) # Output: True__lt__(self, other)
Implements the less‑than (<) comparison.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __lt__(self, other):
return self.x < other.x and self.y < other.y
p1 = Point(2, 3)
p2 = Point(3, 4)
print(p1 < p2) # Output: True__gt__(self, other)
Implements the greater‑than (>) comparison.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __gt__(self, other):
return self.x > other.x and self.y > other.y
p1 = Point(3, 4)
p2 = Point(2, 3)
print(p1 > p2) # Output: True__add__(self, other)
Defines the behavior of the + operator for custom objects.
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)
v1 = Vector(1, 2)
v2 = Vector(3, 4)
result = v1 + v2
print(f"({result.x}, {result.y})") # Output: (4, 6)__sub__(self, other)
Defines the behavior of the subtraction ( -) operator.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
v1 = Vector(3, 4)
v2 = Vector(1, 2)
result = v1 - v2
print(f"({result.x}, {result.y})") # Output: (2, 2)__mul__(self, other)
Defines multiplication behavior, often used for scaling.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __mul__(self, factor):
return Point(self.x * factor, self.y * factor)
p = Point(2, 3)
result = p * 2
print(f"({result.x}, {result.y})") # Output: (4, 6)__call__(self[, args...])
Makes an instance callable like a regular function.
class Calculator:
def __call__(self, a, b):
return a + b
calc = Calculator()
result = calc(3, 4)
print(result) # Output: 7__enter__(self) and __exit__(self, exc_type, exc_value, traceback)
Enable the object to be used as a context manager with the with statement.
class FileManager:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.file = open(self.filename, 'r')
return self.file
def __exit__(self, exc_type, exc_value, traceback):
self.file.close()
with FileManager("example.txt") as file:
contents = file.read()
print(contents)__getattr__(self, name)
Called when attribute lookup fails, allowing custom handling of missing attributes.
class Person:
def __getattr__(self, name):
return f"Attribute '{name}' does not exist."
p = Person()
print(p.age) # Output: Attribute 'age' does not exist.__setattr__(self, name, value)
Intercepts attribute assignment, useful for validation or logging.
class Person:
def __setattr__(self, name, value):
print(f"Setting attribute '{name}' to '{value}'")
super().__setattr__(name, value)
p = Person()
p.name = "Alice" # Output: Setting attribute 'name' to 'Alice'__delattr__(self, name)
Intercepts attribute deletion.
class Person:
def __delattr__(self, name):
print(f"Deleting attribute '{name}'")
super().__delattr__(name)
p = Person()
# Assume p.name exists
p.name = "Bob"
del p.name # Output: Deleting attribute 'name'By mastering these magic methods, developers can write more expressive, Pythonic code and tailor object behavior to fit the needs of automation, APIs, and larger applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
