This is an archived version of the course. Please find the latest version of the course on the main webpage.

Chapter 8: Magic methods

Magic/dunder methods

face Josiah Wang

Remember how the + operator behaves differently when adding two numbers compared to ‘adding’ two strings? The latter concatenates the two strings instead.

You can use another magic method __add__() to achieve this. This will overload the + operator for your specific object class.

For example, we might want to add two Vector instances. This will result in a new Vector instance that adds the x and y attributes of each instance separately. Again, run the following code to see what happens!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Vector: 
    def __init__(self, x, y): 
        self.x = x 
        self.y = y

    def __str__(self): 
        return f"Vector ({self.x}, {self.y})"

    def __add__(self, other): 
        return Vector(self.x + other.x, self.y + other.y)


v1 = Vector(1, 2) 
v2 = Vector(5, 7) 
v3 = v1 + v2
print(v3)

Hopefully this is clear enough! When v1 + v2 occurs, Python will internally invoke v1.__add__(v2).

Here are the other similar magic methods. You can probably figure out which operators they override.

  • __sub__()
  • __mul__()
  • __truediv__()
  • __pow__()

Another quick exercise!

You can also override boolean operators like <, <=, >, >=, ==, and !=. The magic methods are __lt__(), __le__(), __gt__(), __ge__(), __eq__(), and __ne__() respectively.

Your task: implement the __lt__(self, other) method to return True if a person’s age is less than the other person’s age, and False otherwise. So Person("Harry", 11, "uk") < Person("Joe", 18, "uk") should return True.

This should be an easy task - you only need to implement a single line of code!

class Person:
    def __init__(self, name, age, nationality="uk"):
        self.name = name
        self.age = age
        self.nationality = nationality

    def __str__(self):
        return f"A Person {self.name} aged {self.age} from {self.nationality}"

    def __lt__(self, other):
        """ Compare two instances of Person by their age.

        Args:
            other (Person) : the other Person instance against to compare

        Returns:
            bool : True if the person's age is smaller than the other person's age. False otherwise.
        """
        # TODO: Complete this
        pass


assistant1 = Person("Harry", 11, "uk")
assistant2 = Person("Joe", 18, "uk")
print(assistant1 < assistant2)  # should print True
print(assistant2 < assistant1)  # should print False

No peeking at the solutions until you have tried it! 👀

class Person:
    def __init__(self, name, age, nationality="uk"):
        self.name = name
        self.age = age
        self.nationality = nationality

    def __str__(self):
        return f"A Person {self.name} aged {self.age} from {self.nationality}"

    def __lt__(self, other):
        return self.age < other.age