# Python special methods

In Python, special methods (also known as dunder methods) are a set of predefined methods that you can use to enrich your classes. They are also known as "magic methods" because they begin and end with double underscores (e.g. `__init__`).

These methods allow you to define the behavior of certain operations (such as addition, comparison, etc.) that are applied to your objects. For example, you can use the `__len__` method to define the behavior of the len() function when it is called on an instance of your class.

Here is a list of some common special methods in Python:

**Initialization and Construction Description**

* `__new__(cls, other)` To get called in an object's instantiation.
* `__init__(self, other)` To get called by the `__new__` method.
* `__del__(self)` Destructor method.

**Unary operators and functions Description**

* `__pos__(self)` To get called for unary positive e.g. +someobject.
* `__neg__(self)` To get called for unary negative e.g. -someobject.
* `__abs__(self)` To get called by built-in `abs()` function.
* `__invert__(self)` To get called for inversion using the \~ operator.
* `__round__(self, n)` To get called by built-in `round()` function.
* `__floor__(self)` To get called by built-in `math.floor()` function.
* `__ceil__(self)` To get called by built-in `math.ceil()` function.
* `__trunc__(self)` To get called by built-in `math.trunc()` function.

**Augmented Assignment Description**

* `__iadd__(self, other)` To get called on addition with assignment e.g. a +=b.
* `__isub__(self, other)` To get called on subtraction with assignment e.g. a -=b.
* `__imul__(self, other)` To get called on multiplication with assignment e.g. a \*=b.
* `__ifloordiv__(self, other)` To get called on integer division with assignment e.g. a //=b.
* `__idiv__(self, other)` To get called on division with assignment e.g. a /=b.
* `__itruediv__(self, other)` To get called on true division with assignment
* `__imod__(self, other)` To get called on modulo with assignment e.g. a%=b.
* `__ipow__(self, other)` To get called on exponents with assignment e.g. a \*\*=b.
* `__ilshift__(self, other)` To get called on left bitwise shift with assignment e.g. a<<=b.
* `__irshift__(self, other)` To get called on right bitwise shift with assignment e.g. a >>=b.
* `__iand__(self, other)` To get called on bitwise AND with assignment e.g. a&=b.
* `__ior__(self, other)` To get called on bitwise OR with assignment e.g. a|=b.
* `__ixor__(self, other)` To get called on bitwise XOR with assignment e.g. a ^=b.

**Type Conversion Magic Methods Description**

* `__int__(self)` To get called by built-int `int()` method to convert a type to an int.
* `__float__(self)` To get called by built-int `float()` method to convert a type to float.
* `__complex__(self)` To get called by built-int `complex()` method to convert a type to complex.
* `__oct__(self)` To get called by built-int `oct()` method to convert a type to octal.
* `__hex__(self)` To get called by built-int `hex()` method to convert a type to hexadecimal.
* `__index__(self)` To get called on type conversion to an int when the object is used in a slice expression.
* `__trunc__(self)` To get called from `math.trunc()` method.

**String Magic Methods Description**

* `__str__(self)` To get called by built-int `str()` method to return a string representation of a type.
* `__repr__(self)` To get called by built-int `repr()` method to return a machine readable representation of a type.
* `__unicode__(self)` To get called by built-int `unicode()` method to return an unicode string of a type.
* `__format__(self, formatstr)` To get called by built-int `string.format()` method to return a new style of string.
* `__hash__(self)` To get called by built-int `hash()` method to return an integer.
* `__nonzero__(self)` To get called by built-int `bool()` method to return True or False.
* `__dir__(self)` To get called by built-int `dir()` method to return a list of attributes of a class.
* `__sizeof__(self)` To get called by built-int `sys.getsizeof()` method to return the size of an object.

**Attribute Magic Methods Description**

* `__getattr__(self, name)` Is called when the accessing attribute of a class that does not exist.
* `__setattr__(self, name, value)` Is called when assigning a value to the attribute of a class.
* `__delattr__(self, name)` Is called when deleting an attribute of a class.

**Operator Magic Methods Description**

* `__add__(self, other)` To get called on add operation using + operator
* `__sub__(self, other)` To get called on subtraction operation using - operator.
* `__mul__(self, other)` To get called on multiplication operation using \* operator.
* `__floordiv__(self, other)` To get called on floor division operation using // operator.
* `__truediv__(self, other)` To get called on division operation using / operator.
* `__mod__(self, other)` To get called on modulo operation using % operator.
* `__pow__(self, other[, modulo])` To get called on calculating the power using \*\* operator.
* `__lt__(self, other)` To get called on comparison using < operator.
* `__le__(self, other)` To get called on comparison using <= operator.
* `__eq__(self, other)` To get called on comparison using == operator.
* `__ne__(self, other)` To get called on comparison using != operator.
* `__ge__(self, other)` To get called on comparison using >= operator.

There are many other special methods in Python, and you can find a complete list in the [documentation](https://docs.python.org/3/reference/datamodel.html#special-method-names).

```python
# special_methods.py

class Book:
    def __init__(self, title, author, pages):
         """
         __init__ method. The method creates a new instance of a Book class.
         """
        print("A book is created")
        self.title = title
        self.author = author
        self.pages = pages

    def __str__(self):
         """
          __str__ method. This method should return an informal string representation of an object.
         """
        return "Title:{0} , author:{1}, pages:{2} ".format(
            self.title, self.author, self.pages)

    def __len__(self):
         """
          __len__ method. In our case, we print the number of pages of our book.
         """
        return self.pages

    def __del__(self):
         """
          The del keyword deletes an object. It invokes its __del__ method.
         """
        print("A book is destroyed")

book = Book("Inside Steve's Brain", "Leander Kahney", 304)

print(book)
print(len(book))
del book
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pythonforstarters.solomonmarvel.com/object-oriented-programming-in-python/python-special-methods.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
