Hiprup

What are dunder (magic) methods in Python?

Dunder (“double underscore”) methods — also called magic or special methods — are the methods Python calls implicitly to implement language-level behavior on your objects: operators, built-ins, iteration, context management, attribute access, and more. Their names begin and end with __ (e.g. __init__, __len__, __add__).

The data model: defining these methods opts your class into Python’s data model. Instead of calling obj.__len__(), users call len(obj); instead of a.__add__(b), they write a + b. Your class behaves like a built-in.

Common categories:

  • Construction & lifecycle__new__, __init__, __del__.

  • String representations__repr__ (developer-facing, aim to make it unambiguous), __str__ (user-facing), __format__.

  • Equality & ordering__eq__, __hash__, __lt__, __le__, __gt__, __ge__; consider @functools.total_ordering.

  • Numeric operators__add__, __sub__, __mul__, __truediv__, plus reflected (__radd__) and in-place (__iadd__) variants.

  • Containers & iteration__len__, __getitem__, __setitem__, __delitem__, __iter__, __next__, __contains__, __reversed__.

  • Callable__call__ makes an instance callable like a function.

  • Context managers__enter__, __exit__ for with blocks.

  • Attribute access__getattr__, __getattribute__, __setattr__, __delattr__; descriptors via __get__, __set__, __delete__.

  • Async__await__, __aiter__, __anext__, __aenter__, __aexit__.

  • Introspection & meta__class__, __dict__, __slots__, __init_subclass__, __set_name__

class Money:
    def __init__(self, amount, currency='USD'):
        self.amount = amount
        self.currency = currency

    def __repr__(self):
        return f'Money({self.amount}, "{self.currency}")'

    def __str__(self):
        return f'{self.currency} {self.amount:.2f}'

    def __eq__(self, other):
        return self.amount == other.amount and self.currency == other.currency

    def __hash__(self):
        return hash((self.amount, self.currency))

    def __add__(self, other):
        if self.currency != other.currency:
            raise ValueError('Cannot add different currencies')
        return Money(self.amount + other.amount, self.currency)

    def __lt__(self, other):
        return self.amount < other.amount

    def __bool__(self):
        return self.amount != 0

    def __len__(self):
        return int(self.amount)

price = Money(29.99)
tax = Money(5.00)
total = price + tax          # __add__
print(total)                  # __str__: 'USD 34.99'
print(repr(total))            # __repr__: 'Money(34.99, "USD")'
print(price == Money(29.99))  # __eq__: True
print(price < total)          # __lt__: True
print(bool(Money(0)))         # __bool__: False
print(sorted([total, price, tax]))  # Uses __lt__

Money integrates with Python syntax: + calls add, print calls str, repr calls repr, == calls eq, < calls lt, bool() calls bool. sorted() uses lt for ordering. hash enables Money as dict keys. This makes Money behave like a built-in type.

Know the most common dunder methods: init, str, repr, eq, hash, len, add, iter. The str vs repr distinction (human-readable vs developer-readable) is frequently asked.

Show operator overloading (add for +) and context manager (enter/exit for with).

What are dunder (magic) methods in Python? | Hiprup