Python Magic Methods - Using Magic Methods in Python
Python Magic Methods - Using Magic Methods in Python
Python Magic Methods tutorial describes what Python magic methods are and shows how to use
them. In this tutorial we cover some common magic methods.
There are many magic methods in Python. Most of them are used for very specific situations. We
will mention some of the more popular methods.
add_dict.py
#!/usr/bin/env python
class MyDict(dict):
self.update(other)
return MyDict(self)
a = MyDict({'de': 'Germany'})
b = MyDict({'sk': 'Slovakia'})
print(a + b)
In the example, we have a custom dictionary that implements the addition operation with
__add__().
class MyDict(dict):
The custom dictionary inherits from the built-in dict. The __add__() method adds two
dictionaries with the update() method and returns the newly created dictionary.
a = MyDict({'de': 'Germany'})
b = MyDict({'sk': 'Slovakia'})
print(a + b)
$ ./add_dict.py
{'de': 'Germany', 'sk': 'Slovakia'}
init_str.py
#!/usr/bin/env python
class Person:
self.name = name
self.occupation = occupation
def __str__(self):
In the example, we have a Person class with two attributes: name and occupation.
Google Ads -
Sitio O cial
Con Google Ads, no hay
contratos ni mínimo de
Google Ads inversión.
self.name = name
self.occupation = occupation
In the __init__() method we set the instance variables to the values that are passed to the
constructor.
def __str__(self):
$ ./init_str.py
John Doe is a gardener
The __str__() is used to give a human-readable version of the object and the __repr__() a
complete representation of the object. The output of the latter is also more suited for developers.
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
The default implementation of the __repr__() method for an object looks like the above code.
repr_ex.py
#!/usr/bin/env python
class Person:
self.name = name
self.occupation = occupation
def __str__(self):
def __repr__(self):
print(p)
print(repr(p))
The example implements both the __str__() and the __repr__() methods.
$ ./repr_ex.py
John Doe is a gardener
Person{name: John Doe, occupation: gardener}
french_deck.py
#!/usr/bin/env python
import collections
from random import choice
class FrenchDeck:
def __init__(self):
self.total = [Card(suit, rank)
for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self.total)
deck = FrenchDeck()
print(deck[0])
print(len(deck))
print(choice(deck))
We use a named tuple to define a Card class. The namedtuple is a factory function for making a
tuple class. Each card has a suit and a rank.
def __len__(self):
return len(self.total)
The __len__() method returns the number of cards in the deck (52).
print(deck[0])
We get the first card of the deck. This calls the __getitem__().
print(len(deck))
$ ./french_deck.py
Card(suit='heart', rank='2')
52
Card(suit='diamond', rank='A')
char_ex.py
#!/usr/bin/env python
class Char:
def __init__(self, val):
self.val = val
def __int__(self):
return ord(self.val)
def __index__(self):
return ord(self.val)
c1 = Char('a')
print(int(c1))
print(hex(c1))
print(bin(c1))
print(oct(c1))
In the example we create a custom Char class which implements the int(), hex(), bin(), and
oct() functions.
./char_ex.py
97
0x61
0b1100001
0o141
pouch.py
#!/usr/bin/env python
import collections
class Pouch:
def __init__(self):
self.bag = []
self.bag.append(coin)
def __eq__(self, other):
if val1 == val2:
return True
else:
return False
def __str__(self):
return str(self.bag)
val1 = 0
val2 = 0
if coin.rank == 'g':
val1 += 6
if coin.rank == 's':
val1 += 3
if coin.rank == 'b':
val1 += 1
if coin.rank == 'g':
val2 += 6
if coin.rank == 's':
val2 += 3
if coin.rank == 'b':
val2 += 1
pouch1 = Pouch()
pouch1.add(Coin('g'))
pouch1.add(Coin('g'))
pouch1.add(Coin('s'))
pouch2 = Pouch()
pouch2.add(Coin('g'))
pouch2.add(Coin('s'))
pouch2.add(Coin('s'))
pouch2.add(Coin('b'))
pouch2.add(Coin('b'))
pouch2.add(Coin('b'))
print(pouch1)
print(pouch2)
if pouch1 == pouch2:
print('Pouches have equal value')
if val1 == val2:
return True
else:
return False
In the __eq__() method, we first evaluate the values of the two pouches. Then we compare them
and return a boolean result.
val1 = 0
val2 = 0
if coin.rank == 'g':
val1 += 6
if coin.rank == 's':
val1 += 3
if coin.rank == 'b':
val1 += 1
if coin.rank == 'g':
val2 += 6
if coin.rank == 's':
val2 += 3
if coin.rank == 'b':
val2 += 1
The __evaluate() method calculates the values of the two pouches. It goes through the coins of
the pouch and adds a value according to the rank of the coin.
pouch1 = Pouch()
pouch1.add(Coin('g'))
pouch1.add(Coin('g'))
pouch1.add(Coin('s'))
if pouch1 == pouch2:
print('Pouches have equal value')
2D vector example
In the following example, we introduce a couple of other magic methods, including __sub__(),
__mul__(), and __abs__().
vector.py
#!/usr/bin/env python
import math
class Vec2D:
self.x = x
self.y = y
def __abs__(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
def __str__(self):
return f'({self.x}, {self.y})'
u = Vec2D(0, 1)
v = Vec2D(2, 3)
w = Vec2D(-1, 1)
a = u + v
print(a)
print(a == w)
a = u - v
print(a)
a = u * v
print(a)
print(abs(u))
print(u == v)
print(u != v)
In the example, we have a Vec2D class. We can compare, add, subtract, and multiply vectors. We
can also calculate the lenght of a vector.
$ ./vector.py
(2, 4)
False
(-2, -2)
3
1.0
False
True