Special methods

Intermediate

Introduction

Methods with double underscores on both sides, such as __init__, are special methods. Python calls them for you when you use built-in operations: print, +, ==, len() and more.

A class of your own can feel as natural as a number or a list. Special methods are the hooks that let your objects work with print, +, == and len, so code that uses them reads like ordinary Python.

How it works

Printing an object

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

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

p = Point(3, 4)
print(p)
Open in compiler

Without __str__, print(p) would show something like <Point object at 0x...>. With it, Python calls p.__str__() to get the text. Step through print(p) and watch the __str__ frame appear on the call stack.

len()

class Playlist:
    def __init__(self, songs):
        self.songs = songs

    def __len__(self):
        return len(self.songs)

mix = Playlist(["a", "b", "c"])
print(len(mix))
Open in compiler

len(mix) calls mix.__len__(). Implementing the special methods that fit your class makes it feel like a built-in type.

You writePython calls
print(x), str(x)x.__str__()
x + yx.__add__(y)
x == yx.__eq__(y)
len(x)x.__len__()

Syntax

class Money:
    def __init__(self, taka):
        self.taka = taka

    def __str__(self):
        return f"{self.taka} taka"

    def __add__(self, other):
        return Money(self.taka + other.taka)

Example

class Money:
    def __init__(self, taka):
        self.taka = taka

    def __add__(self, other):
        return Money(self.taka + other.taka)

    def __eq__(self, other):
        return self.taka == other.taka

    def __str__(self):
        return f"{self.taka} taka"

total = Money(150) + Money(250)
print(total)
print(total == Money(400))
Open in compiler
  • a + b calls a.__add__(b), which here returns a new Money object.
  • a == b calls a.__eq__(b). Without it, == only checks whether both names point to the same object.

The objects panel shows the temporary Money objects being created and the result being kept in total.

Line by line

  1. Money(150) + Money(250) makes two objects and then calls __add__.
  2. __add__ returns a new Money holding 400, and it is stored in total.
  3. print(total) calls __str__, which gives 400 taka.
  4. total == Money(400) calls __eq__, which compares the amounts.

Expected result

400 taka
True

In the real world

Python's own datetime objects support subtraction this way, and the Fraction and Decimal types behave just like numbers. Scientific libraries use special methods so that matrix code looks like the maths it represents.

Common mistakes

  • Returning something other than text from __str__, which raises a TypeError.
  • Changing self inside __add__ instead of returning a new object: a + b should not change a.
  • Calling special methods directly (p.__str__()) in normal code; use str(p) and let Python call them.

Best practices

  • Add __str__ to almost every class you write.
  • Only overload an operator when its meaning is obvious.
  • Keep __add__ free of side effects.

Summary

Special methods connect a class to Python's built-in operations. __str__ gives the printed form, __add__ and __eq__ give + and == their meaning, and __len__ supports len.

Practice

Give the Point class an __add__ that adds coordinates and an __eq__ that compares them, then check that Point(1, 2) + Point(3, 4) == Point(4, 6).

Quick check

1. Which method does print(obj) use?
2. What does a + b call?
3. Without __eq__, when is a == b True for two objects?

Key takeaways

  • print calls __str__ and == calls __eq__.
  • __add__ should return a new object.
  • Let Python call special methods, rather than calling them yourself.

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.