Printing an object with __str__
When you print an object of your own class, Python doesn't know which of its data matters, so it prints the class's name and the object's address in memory, something like this:
<__main__.Match object at 0x7f8e2a4b3d10>
That's no use to anyone, and the address changes on every run. A class can say how its objects should be shown by having a method called __str__. It returns a string that describes the object's state, and print uses it:
class Match:
def __init__(self, home, away):
self.home = home
self.away = away
self.home_goals = 0
self.away_goals = 0
def goal(self, team):
if team == self.home:
self.home_goals += 1
else:
self.away_goals += 1
def __str__(self):
return f"{self.home} {self.home_goals}-{self.away_goals} {self.away}"
final = Match("Lions", "Tigers")
print(final)
final.goal("Lions")
final.goal("Tigers")
final.goal("Lions")
print(final)
Lions 0-0 Tigers
Lions 2-1 Tigers__str__ has two underscores on each side, like __init__. Methods with names like these are special methods: you don't call them yourself, Python calls them when it needs them. It calls __init__ when an object is made, and __str__ whenever the object has to be turned into a string. That happens in print, in the function str and in f-strings:
class Match:
def __init__(self, home, away):
self.home = home
self.away = away
self.home_goals = 3
self.away_goals = 3
def __str__(self):
return f"{self.home} {self.home_goals}-{self.away_goals} {self.away}"
cup = Match("Owls", "Foxes")
text = str(cup)
print(len(text))
print(f"Full time: {cup}")
14
Full time: Owls 3-3 FoxesReturn the string, don't print it
__str__ must return a string. A common mistake is to print it inside the method instead. The method then returns None, and Python stops:
class Match:
def __init__(self, home, away):
self.home = home
self.away = away
def __str__(self):
print(f"{self.home} vs {self.away}")
game = Match("Owls", "Foxes")
print(game)
Owls vs FoxesTraceback (most recent call last):
File "main.py", line 11, in <module>
print(game)
~~~~~^^^^^^
TypeError: __str__ returned non-string (type NoneType)The line was printed by the print inside __str__, and then print(game) got None back instead of a string.
One more thing: printing a whole list of objects, such as print([final, cup]), still shows the addresses, because a list shows its items in another way. Print the objects one at a time in a loop instead.