magic methods (python meetup)
TRANSCRIPT
What are magic methods?
● Methods with double underscores at the beginning and the end○ __init__○ __str__
● Where is magic?○ Magic methods are not invoked directly!
How magic methods are invoked?
● Calling Python’s built in functions
len([1, 2, 3])
● Using operators
1 + 1
5 > 3
● Using for loop
for x in [1, 2, 3]:
print(x)
Which methods are invoked?
● Calling Python’s built in functions
len([1, 2, 3]) # __len__()
● Using operators
1 + 1 # __add__()
5 > 3 # __gt__()
● Using for loop
for x in [1, 2, 3]: # __iter__()
print(x) # __next__()
Example: __str__
from datetime import datetime
x = datetime.now()
print(x)
>> 2017-02-21 18:15:02.161633
Magic method:
x.__str__()
Example: __setitem__
x = {1: ‘a’, 2: ‘3’}
x[3] = ‘c’ # x.__setitem__(self, name, value)
Another magic method:
3.__hash__()
● Must be implemented if instance is used in hashable collections
● Returns integer, immutable for instance
● Works with __cmp__ or __eq__
When to implement?
● to control string representation of an object○ __repr__○ __str__
● to initialize an instance○ __init__
● when writing libraries, frameworks○ to make objects behave like built-in types○ Django example:
■ model_instance_a == model_instance_b
Implementing: __init__
● “Constructor”○ __new__○ __init__
● Example
class ComplexNumber:
def __init__(self, x, y):
self.x = x # x = Re
self.y = y # y = Im
z = ComplexNumber(3, 5)
Implementing: __str__
● string representation of an object○ str(x)○ print(x)
● Example
class ComplexNumber:...
def __str__(self):
return ‘{} + {}i’.format(self.x, self.y)
Operator overloading: +
complex_number_a = ComplexNumber(3, 5)
complex_number_b = ComplexNumber(2, 1)
complex_number_a + complex_number_b
>> TypeError
● Magic method○ __add__○ complex_number_a.__add__(complex_number_b)
Operator overloading: +
● Magic method○ __add__
● Example
class ComplexNumber:...
def __add__(self, other):
real = self.x + other.x
imag = self.y + other.y
return ComplexNumber(real, imag)
Operator overloading: +
complex_number_a = ComplexNumber(3, 5)
complex_number_b = ComplexNumber(2, 1)
complex_number_a + complex_number_b
>> 5 + 6i
complex_number_a + 4
>> AttributeError
'int' object has no attribute 'x'
Operator overloading: +
● Magic method○ __add__
● Example
class ComplexNumber:…
def __add__(self, other):
if isinstance(other, ComplexNumber):real = self.x + other.ximag = self.y + other.yreturn ComplexNumber(real, imag)
else:return ComplexNumber(self.x + other, self.y)
Operator overloading: +
complex_number_a = ComplexNumber(3, 5)
complex_number_a + 4
>> 7 + 5i
4 + complex_number_a
>> TypeError
unsupported operand type(s) for +: 'int' and 'ComplexNumber'
Operator overloading: +
● Magic method○ __radd__
● Example
class ComplexNumber:...
def __radd__(self, other):
return self + other
Operator overloading: +
complex_number_a = ComplexNumber(3, 5)
4 + complex_number_a
>> 7 + 5i
complex_number_a += 4
>> 7 + 5i
Implementing: __all__
● example : django/db/__init__.py
__all__ = ['backend', 'connection', 'connections', ...]
● controls * imports
from django.db import *
When not to implement?
class ComplexNumber():
...
def __del__(self):
self.connection.close() # :(
...
del counter # ?
Magic method:
__del__ is called by garbage collector!
Python 2 and Python 3
● String representation○ Python 2: __str__ and __unicode__○ Python 3: __str__
● Boolean○ Python 2: __nonzero__○ Python 3: __bool__
● Comparison○ Python 2: __cmp__○ Python 3: uses other magic methods