Magic methods in Python are the special methods that start and end with the double underscores. They are also called dunder methods. Magic methods are not meant to be invoked directly by you, but the invocation happens internally from the class on a certain action.
Category | Methods |
---|---|
Arithmetic operators | __add__ , __sub__ , __mul__ , __truediv__ , __floordiv__ , __mod__ , __divmod__ , __pow__ , __radd__ , __rsub__ , __rmul__ , __rtruediv__ , __rfloordiv__ , __rmod__ , __rdivmod__ , __rpow__ , __iadd__ , __isub__ , __imul__ , __itruediv__ , __ifloordiv__ , __imod__ , __ipow__ , __neg__ , __pos__ , __abs__ , __round__ , __floor__ , __ceil__ . |
Bitwise Operations | __and__ , __invert__ , __or__ , __xor__ , __rxor__ |
Comparison Operations | __and__ , __or__ , __xor__ , __invert__ , __lshift__ , __rshift__ |
Type Conversion | __bool__ , __int__ , __float__ , __complex__ , __index__ , __bytes__ , __str__ , __repr__ |
Container methods | __len__ , __getitem__ , __setitem__ , __delitem__ , __contains__ , __iter__ , __next__ , __reversed__ , __missing__ , __call__ |
Attribute methods | __getattr__ , __getattribute__ , __setattr__ , __delattr__ |
Other special methods | __enter__ , __exit__ , __hash__ , __new__ , __init__ , __del__ , __call__ , __dir__ , __format__ , __getnewargs__ , __subclasshook__ , __instancecheck__ , __subclasscheck__ , __prepare__ , __annotations__ , __locals__ , __globals__ , __qualname__ , __name__ , __module__ , __doc__ , __class__ , __init_subclass__ , __sizeof__ , __trunc__ , __floor_division__ , __bit_length__ , __conjugate__ , __real__ , __imag__ , __complex__ |
__abs__(self)
- used to return the absolute value of an object.__add__(self, other)
- used to define the behavior of the addition operator (+) for an object.__and__(self, other)
- used to define the behavior of the bitwise AND operator (&) for an object.__bool__(self)
- used to return the boolean value of an object.__ceil__(self)
- used to return the ceiling value of an object.__class__(self)
- used to return the class of an object.__delattr__(self, name)
- used to delete an attribute from an object.__dir__(self)
- used to return a list of valid attributes for an object.__divmod__(self, other)
- used to define the behavior of the divmod() function for an object.__doc
- used to store the documentation string for a class or function.__eq__(self, other)
- used to define the behavior of the equality operator (==) for an object.__float__(self)
- used to convert an object to a floating-point number.__floor__(self)
- used to return the floor value of an object.__floordiv__(self, other)
- used to define the behavior of the floor division operator (//) for an object.__format__(self, format_spec)
- used to define the behavior of the str.format() method for an object.__ge__(self, other)
- used to define the behavior of the greater than or equal to operator (>=) for an object.__getattribute__(self, name)
- used to get the value of an attribute from an object.__getnewargs__(self)
- used to return the arguments for the object constructor.__gt__(self, other)
- used to define the behavior of the greater than operator (>) for an object.__hash__(self)
- used to return the hash value of an object.__index__(self)
- used to return the integer value of an object.__init__(self)
- used to initialize an object.__init_subclass(cls)
- used to initialize a subclass.__int__(self)
- used to convert an object to an integer.__invert__(self)
- used to define the behavior of the bitwise NOT operator (~) for an object.__le__(self, other)
- used to define the behavior of the less than or equal to operator (<=) for an object.__lshift__(self, other)
- used to define the behavior of the left shift operator (<<) for an object.__lt__(self, other)
- used to define the behavior of the less than operator (<) for an object.__mod__(self, other)
- used to define the behavior of the modulo operator (%) for an object.__mul__(self, other)
- used to define the behavior of the multiplication operator (*) for an object.__ne__(self, other)
- used to define the behavior of the not equal operator (!=) for an object.__neg__(self)
- used to define the behavior of the negation operator (-) for an object.__new(cls, *args, kwargs)
- used to create a new instance of a class. This method is called before init() and is responsible for creating and returning the new object.__or__(self, other)
- used to define the behavior of the bitwise OR operator (|) for an object.__pos__(self)
- used to define the behavior of the unary plus operator (+) for an object.__pow__(self, other[, modulo])
- used to define the behavior of the exponent__rsub__(self, other)
- used to define the behavior of the subtraction operator (-) when the object is on the right-hand side.__rtruediv__(self, other)
- used to define the behavior of the true division operator (/) when the object is on the right-hand side.__rxor__(self, other)
- used to define the behavior of the bitwise XOR operator (^) when the object is on the right-hand side.__setattr__(self, name, value)
- used to set the value of an attribute on an object.__sizeof__(self)
- used to return the size of an object in bytes.__str__(self)
- used to return a string representation of an object.__sub__(self, other)
- used to define the behavior of the subtraction operator (-) for an object.__subclasshook__(cls, subclass)
- used to customize the behavior of the issubclass()
built-in function.__truediv__(self, other)
- used to define the behavior of the true division operator (/) for an object.__trunc__(self)
- used to return the truncated integer value of a float or decimal number.__xor__(self, other)
- used to define the behavior of the bitwise XOR operator (^) for an object.__bit_length__(self)
- used to return the number of bits required to represent an integer in binary.__conjugate__(self)
- used to return the complex conjugate of a complex number.__denominator__(self)
- used to return the denominator of a rational number.__from_bytes(bytes, byteorder, *, signed=False)
- used to convert a sequence of bytes into an integer.__imag__(self)
- used to return the imaginary part of a complex number.__numerator__(self)
- used to return the numerator of a rational number.__real__(self)
- used to return the real part of a complex number.__to_bytes__(self, length, byteorder, *, signed=False)
- used to convert an integer into a sequence of bytes.new | init | |
---|---|---|
1 | Called before init | Called after new |
2 | Accepts a type as the first argument | Accepts an instance as the first argument |
3 | Is supposed to return an instance of the type received | Is not supposed to return anything |
4 | Used to control instance creation | Used to initialize instance variables |
Talking about the first point. __new__
is called when the instance is first created. This happens before the initialization of the class.
also its important to mention that the first argument to __init__
is always self
This self is the instance of the class. self
is what __new__
returns.
Coming to the third point, __new__
is supposed to return an instance of the class. Note that if __new__
does not returns anything, __init__
is not called.
If you are coming from another language, you might be surprised that there are two similar things doing the same kind of work. Most languages have something called a constructor.
In Python, that concept is broken down into constructor and initializer. And __new__
is the constructor and __init__
is the initializer.
Please note that __new__
is implicit. Meaning that if you don’t actually need to modify the creation of an instance of the class, you don’t need to have a new
method.
instance variables are local to an instance. So anything you are doing in init is local to that instance only. But anything you are doing in new will be affecting anything created for that type.
Consider this example:
class Demo:
def __new__(cls, *args):
print("__new__ called")
return object.__new__(cls)
def __init__(self):
print("__init__ called")
d = Demo()
This is the simplest example of both __new__
and __init__
in action. If you save the above code in a file and run it, you’d see something like this:
$ python3 in_it.py
__new__ called
__init__ called
As you can see, the new method is called first and then execution is passed to the init method.
Use case for __new__
:
One of the best use cases we can take an example of is when creating a Singleton. As we know, Singleton ensures a class only has one instance and provides a global point of access to it.
Some of the places singleton are used is in game programming where there is only one instance of the player. Doesn’t matter how many instances you create, you’ll end up having only one.
Let’s see how to achieve similar behavior in Python:
class Singleton:
__instance = None
def __new__(cls):
if cls.__instance is None:
print("creating...")
cls.__instance = object.__new__(cls)
return cls.__instance
s1 = Singleton()
s2 = Singleton()
print(s1)
print(s2)
Output:
$ python3 singleton.py
creating...
<__main__.Singleton object at 0x7f943301d350>
<__main__.Singleton object at 0x7f943301d350>
As you can see, creating…
is printed only once. they both point to the same memory location. In my case, it’s 0x7f943301d350
.
You might be guessing that can’t we do the same thing with __init__
? No! That’s because __init__
does not return anything. We’ll see in the next section what __init__
is well suited for.
Use case for __init__
:
As we have already seen previously. init
is there to initialize an instance variable. These instance variables can later be used in different methods of the instance.
Here I’ll demonstrate one such example:
class Window(QWidget):
def __init__(self, parent = None):
super(Window, self).__init__(parent)
self.resize(200, 100)
self.setWindowTitle("My App")
When initializing UI objects, you can set how wide or long the window could be. You can also read preferences from a file and apply that during the initialization phase of an application. Setting the window title could be another example.