In this lesson, you'll learn about __str__() and __repr__(), two dunder methods in Python that are used to better document your custom objects.
Readability
The __str__() method helps you to create user-friendly output that describes your object when calling print() or str() on it. You can think of it as being aimed at an end-user.
Str Method Example
Remember seeing output such as <class '__main__.Ingredient'> when you've tried to print your objects? That doesn't seem very descriptive. If you want to show different output when you call print() on an Ingredient() object, you'll have to implement __str__():
class Ingredient:
"""Models a food item used as an ingredient."""
def __init__(self, name, amount):
self.name = name
self.amount = amount
def expire(self):
"""Expires the ingredient."""
print(f"whoops, these {self.name} went bad...")
self.name = "expired " + self.name
def __str__(self):
return f"{self.name} ({self.amount})"
In this example code, you've decided that you want to represent an Ingredient() object to your users as name (amount). You did this by implementing __str__() so that it returns a string consisting of the relevant instance variables self.name and self.amount, as well as some minimal formatting.
If you now call print() and pass it to one of your custom objects, you'll see this output:
c = Ingredient("carrot", 5)
print(c) # OUTPUT: carrot (5)
This new output is more user-friendly and contains all the information that your user will probably want to see when they print() an ingredient.
When you don't implement the __str__() method, Python will fall back to the output of __repr__() when print() is called on a custom object.
Documentation
The __repr__() method is similar to __str__(). The difference between the two is that __repr__() should return an unambiguous description of an object of that class.
class Ingredient:
"""Models a food item used as an ingredient."""
def __init__(self, name, amount):
self.name = name
self.amount = amount
def expire(self):
"""Expires the ingredient."""
print(f"whoops, these {self.name} went bad...")
self.name = "expired " + self.name
def __str__(self):
return f"{self.name} ({self.amount})"
def __repr__(self):
return f"Ingredient(name={self.name}, amount={self.amount})"
This output should be very clear and concise, but can often turn out to be less user-friendly than __str__(). You can think of it as being aimed at developers and should help them to debug potential issues:
c = Ingredient("carrot", 5)
print(c) # OUTPUT: carrot (5)
print(repr(c)) # OUTPUT: Ingredient(name=carrot, amount=5)
Every custom class needs to have the __repr__() method implemented. If you don't write it yourself, then the default is used, which gives you the output you've seen before: <class '__main__.Ingredient'>.
Tasks
- Implement both
__repr__()and__str__()in yourIngredient()class. - Create some objects and print them out, commenting out the first one, then the other dunder method.
In the next lesson, you'll implement __add__() as an example of how you can prepare your custom objects to work in a way that's familiar to other Python developers.
Additional Resources
- Dan Bader: The difference between
__repr__and__str__
Summary: Python Dunder Documentation
__str__()is used to change the output when callingprint()orstr()__repr__()is like str but returns an unambiguous representation of the object__repr__()and__str__()are both for understanding and debugging your classes- If choosing only one, make sure it's
__repr__()