# Python Magic Methods (Dunder Methods)

Magic methods in Python are the special methods that start and end with double underscores. They are also known as "dunder" methods (double underscore). They allow you to define how objects of your class behave with built-in operations.

## Common Magic Methods

### Initialization and Representation

*   `__init__(self, ...)`: The constructor method, called when an object is created.
*   `__str__(self)`: Returns a string representation of the object, used by `print()` and `str()`.
*   `__repr__(self)`: Returns an "official" string representation of the object, used by `repr()`.

```python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"{self.name} ({self.age})"

    def __repr__(self):
        return f"Person(name='{self.name}', age={self.age})"

p = Person("Alice", 30)
print(str(p))  # Output: Alice (30)
print(repr(p)) # Output: Person(name='Alice', age=30)
```

### Arithmetic Operators

You can overload arithmetic operators using magic methods.

*   `__add__(self, other)`: Implements addition `+`.
*   `__sub__(self, other)`: Implements subtraction `-`.
*   `__mul__(self, other)`: Implements multiplication `*`.
*   `__eq__(self, other)`: Implements equality `==`.

```python
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 __str__(self):
        return f"Vector({self.x}, {self.y})"

v1 = Vector(2, 4)
v2 = Vector(1, 3)
print(v1 + v2) # Output: Vector(3, 7)
```

### Container Methods

*   `__len__(self)`: Implements `len()`.
*   `__getitem__(self, key)`: Implements indexing `obj[key]`.

[[programming/python/python]]