Dunder Methods in Python
Tags: python, oop, beginners, coding
Published: 2024-05-24 15:34:16


Python's  magic methods are commonly used for operator overloading.

Python's *dunder* methods, also known as magic methods, are special methods that are invoked automatically when certain operators or functions are used on an object.

> dunder means *double under* for double underscore

> You can use the `dir` function to see the magic methods inherited by a class

# Case Study

Lets give an example of an `Item` class in python

```python
class Item:
  
  def __init__(self, name, price):
    self.name = name
    self.price = price
```

The `__init__` method is called everytime an instance of a class is created. It is also a magic method

---
## The `__str__` method

```python
def __str__(self):
    return f'Item({self.name} for {self.price})'
```

The `__str__` method is called whenever the class is converted into a string.
So when the `print` function is called on an instance of the class

```python
>> i1 = Item("Fridge", 1000)
>> print(i1)
#... Item(Fridge for 1000)
```

## The `__repr__` method

`repr` performs the same function as `str`  but is used in different situations. `repr` is used in debugging situations and contains a detailed description of the object. 

> If a `__str__` method is not defined, Python will default to calling the `__repr__` method

---
## The `__add__` method

The `__add__` method is called whenever the `+` operator is performed on an instance of a class. For instance

**For instance**

```python
i1 = Item("Fridge", 1000)
i2 = Item("Waffles",25)
print(i1 + i2)
```

This code returns

```
Traceback (most recent call last):
  File "main.py", line x, in <module>
    print(i1 + i2)
TypeError: unsupported operand type(s) for +: 'Item' and 'Item'
```

So we declare an `add` function that can support operand types for `+`

```python
def __add__(self, other): # other for the second operand
    newItem = Item(f'({self.name},{other.name})', self.price + other.price)
    return newItem
```

so, calling `i1 + i2` above will result in

```
Item(Fridge,Waffles for 1025)
```

> It is advisable for dunder_methods like this to return the same type as its operands.

**For Instance**

```python
>> i1 = Item("Fridge", 1000)
>> i2 = Item("Waffles",25)
>> i3 = Item("Samsung", 500)
>> print(i1 + i2 + i3)

#... Item(Fridge,Waffles,Samsung for 1525)
```

There are still other arithmetic dunder_methods that are commonly used such as

| Dunder Method  | Operator or Inbuilt function |
| -------------- | ---------------------------- |
| `__add__`      | `+`                          |
| `__sub__`      | `-`                          |
| `__mul__`      | `*`                          |
| `__truediv__`  | `/`                          |
| `__floordiv__` | `//`                         |
| `__pow__`      | `**`                         |

---
# The `__gt__` method

The `eq, ne, gt, le, lt, ge` methods are sets of magic methods used for comparism. Likewise

| Dunder Method | Operator or Inbuilt Function |
| ------------- | ---------------------------- |
| `__eq__`      | `==`                         |
| `__ne__`      | `!=`                         |
| `__gt__`      | `>`                          |
| `__le__`      | `<=`                         |
| `__lt__`      | `<`                          |
| `__ge__`      | `>=`                         |
> The drawback to  overloading comparision operators is that **if you overload  one of them, you have to overload the whole six of them**

**For Example**

```python
def __gt__(self, other):
    return self.price > other.price
```

Using the `gt` method to check if an item is more constly than the other.

> It is best practice for your comparision overloads to return **boolean values**

---
This is just a quick overview of what magic methods are in python and how operator overloading works.

**Just keep in mind that for every built-in method and operator, there is a  corresponding  dunder method for it**

For more dunder methods check [here](https://www.pythonmorsels.com/every-dunder-method/#cheat-sheet)
The complete code for my example is kept [here](https://onecompiler.com/python/42e6k47ka)

If you have any questions, please feel free to ask 😊 below in the comments