__str__, __repr__ and __eq__
In the previous lesson, we filled in cards from a blueprint. Now imagine a card has to be shown to someone or compared with another one. A person would first read what is written on it. Python cannot do that: it can neither show a new class's instance readably nor compare it by content.
Let's look at a point with coordinates:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(1, 2)
print(p == Point(1, 2)) # False
print(p)There are two surprises here:
p == Point(1, 2)givesFalse, although the coordinates are the same;- the last line prints something like
<__main__.Point object at 0x7f3a2c1b2d50>: the class name and the object's address in memory, which changes from run to run.
By default, == checks whether it is the same object, not whether the coordinates match. A class can replace both behaviors with its own.
Special methods
Methods whose names begin and end with two underscores are special methods. They are usually not called by name. Python calls them itself in certain situations, as it calls __init__ when an instance is created.
A class has two such methods for showing an object. They answer different questions, so let's take each one.
__str__ — for people
The __str__ method returns a string for the program's reader. print, str() and f-strings show it. It is like a caption on the card in large letters: "point (1, 2)".
__repr__ — for the programmer
The __repr__ method returns a string for the programmer. The repr() function shows it, and so do lists, tuples and dicts for their elements. The text of __repr__ usually looks like the call that creates the same object: Point(1, 2).
Let's put both methods into one class:
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return f"({self.x}, {self.y})"
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(1, 2)
print(p) # (1, 2)
print([p, Point(3, 4)]) # [Point(1, 2), Point(3, 4)]
print(f"p = {p}", repr(p)) # p = (1, 2) Point(1, 2)Let's go through the output line by line:
print(p)calls__str__and prints(1, 2).print([p, Point(3, 4)])prints a list, and a list shows each element through__repr__.- An f-string takes
__str__, andrepr(p)takes__repr__.
Here unpacking writes the __init__ line more briefly: self.x, self.y = x, y. The quotes in ['a'] are part of __repr__ too: that is how a string shows itself.
The order of methods in a class does not matter. If a class has no __str__, print uses __repr__. So if you write only one of the two, write __repr__.
Comparing with __eq__
Picture two copies of the same book. Their text is the same, but there are two books on the shelf, not one. In Python, these are two different questions:
a is basks whether it is one object;a == basks whether the objects are equal by content.
Without a method of its own, a class's == answers the first question, like is: an object equals only itself. The __eq__(self, other) method defines comparison by content. Python calls it for a == b, passing a as self and b as other:
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
p = Point(1, 2)
print(p == Point(1, 2), p is Point(1, 2)) # True False
print(p != Point(3, 4)) # True__eq__ returns True or False. Python derives the != operator from __eq__ itself. The method does not affect is: two calls of Point(1, 2) create different objects.
other receives any object to the right of ==. Here p == 5 stops with an AttributeError, because a number has no attribute x.
Interviewers like to ask: "How does == differ from is?" is compares objects by identity, that is, it checks whether they are one object. == calls __eq__ and compares by content, if the class defines it.
Common mistake
__str__ returns a number instead of a string:
class Point:
def __init__(self, x):
self.x = x
def __str__(self):
return self.x # ✗
print(Point(1))TypeError: __str__ returned non-string (type int)print requires __str__ and __repr__ to return a str. Build the string with an f-string: return f"{self.x}".
Key points
__str__gives the string forprint,str()and f-strings, and__repr__the one for the programmer and for list elements.- Without
__str__,printuses__repr__. - Without
__eq__,==compares objects likeis;__eq__defines comparison by content. __str__and__repr__must return astr.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.