Python Dunder (Magic) Methods – Complete Guide with Demos
Click Run to execute examples or Copy to copy code. Works directly inside Blogger.
Dunder methods, also known as magic methods or special methods, are a core feature in Python that allow classes to interact with the language's built-in functions and operators. The term "dunder" is a contraction of "double underscore," referring to the fact that these methods are named with double underscores at both the beginning and end (e.g., __init__, __add__, __str__).
Key characteristics of dunder methods:
Implicit Invocation: Dunder methods are typically not called directly by the programmer. Instead, they are implicitly invoked by the Python interpreter in response to specific actions or operations. For example, when you use the + operator on two objects, Python implicitly calls the __add__ dunder method of the first object.
Operator Overloading: Dunder methods enable operator overloading, allowing you to define custom behavior for operators (like +, -, *, ==, []) when applied to instances of your classes. This makes your custom objects behave more like native Python types. Integration with Built-in Functions: Many built-in Python functions (such as len(), str(), int()) rely on corresponding dunder methods (__len__, __str__, __int__) to determine how they should interact with instances of your classes.
Customizing Class Behavior: Dunder methods allow you to customize various aspects of your class's behavior,
including object initialization (__init__), object representation (__str__, __repr__), attribute access (__getattr__, __setattr__), and iteration (__iter__, __next__).
Examples of common dunder methods:
- __init__: Called when a new instance of a class is created, used for initialization.
- __str__: Defines the informal string representation of an object (what print() shows).
- __repr__: Defines the official string representation of an object, often used for debugging.
- __add__, __sub__, __mul__: Define behavior for arithmetic operations.
- __len__: Defines the behavior of the len() function for an object.
- __getitem__, __setitem__: Define behavior for indexing and slicing (e.g., obj[key]).
By implementing dunder methods in your classes, you can create more robust, intuitive, and "Pythonic" custom objects that seamlessly integrate with the language's features.
__init__ – Initialize instance attributes
class Person:
def __init__(self, name):
self.name = name
print("Hello", self.name)
Person("Alice")
__repr__ – Developer representation
class Point:
def __init__(self, x, y): self.x, self.y = x, y
def __repr__(self): return f"Point({self.x},{self.y})"
p = Point(2,3)
print(repr(p))
__str__ – User-friendly string
class Point:
def __init__(self, x, y): self.x, self.y = x, y
def __str__(self): return f"({self.x},{self.y})"
print(Point(1,4))
__add__ – Add two objects
class Vec:
def __init__(self, x, y): self.x, self.y = x, y
def __add__(self, o): return Vec(self.x + o.x, self.y + o.y)
def __repr__(self): return f"Vec({self.x},{self.y})"
print(Vec(1,2)+Vec(3,4))
__len__ – Object length
class L:
def __init__(self, data): self.data = data
def __len__(self): return len(self.data)
print(len(L([1,2,3])))
__getitem__ – Index access
class Seq:
def __init__(self): self.data = [10,20,30]
def __getitem__(self, k): return self.data[k]
s = Seq()
print(s[1])
__call__ – Make instance callable
class Adder:
def __init__(self, n): self.n = n
def __call__(self, x): return x + self.n
add5 = Adder(5)
print(add5(10))
__enter__ / __exit__ – Context manager
class Ctx:
def __enter__(self): print("enter"); return self
def __exit__(self,exc,val,tb): print("exit")
with Ctx(): print("inside")
__bool__ – Truth value
class C:
def __init__(self, items): self.items = items
def __bool__(self): return len(self.items) > 0
print(bool(C([])), bool(C([1])))
__hash__ – Hashable object
class H:
def __init__(self,v): self.v=v
def __hash__(self): return hash(self.v)
print({H(5): 'ok'})
No comments:
Post a Comment