Improving Object Representation with __repr__
In Python, objects can be represented as strings in two different ways. These representations serve different purposes and are useful in various scenarios.
The first type is the string representation. This is created by the str()
function, which is automatically called when you use the print()
function. The string representation is designed to be human-readable. It presents the object in a format that is easy for us to understand and interpret.
The second type is the code representation. This is generated by the repr()
function. The code representation shows the code that you would need to write to recreate the object. It's more about providing a precise and unambiguous way to represent the object in code.
Let's look at a concrete example using Python's built-in date
class. This will help you see the difference between the string and code representations in action.
>>> from datetime import date
>>> d = date(2008, 7, 5)
>>> print(d) ## Uses str()
2008-07-05
>>> d ## Uses repr()
datetime.date(2008, 7, 5)
In this example, when we use print(d)
, Python calls the str()
function on the date
object d
, and we get a human-readable date in the format YYYY-MM-DD
. When we simply type d
in the interactive shell, Python calls the repr()
function, and we see the code needed to recreate the date
object.
You can explicitly get the repr()
string in various ways. Here are some examples:
>>> print('The date is', repr(d))
The date is datetime.date(2008, 7, 5)
>>> print(f'The date is {d!r}')
The date is datetime.date(2008, 7, 5)
>>> print('The date is %r' % d)
The date is datetime.date(2008, 7, 5)
Now, let's apply this concept to our Stock
class. We're going to improve the class by implementing the __repr__
method. This special method is called by Python when it needs the code representation of an object.
To do this, open the file stock.py
in your editor. Then, add the __repr__
method to the Stock
class. The __repr__
method should return a string that shows the code needed to recreate the Stock
object.
def __repr__(self):
return f"Stock('{self.name}', {self.shares}, {self.price})"
After adding the __repr__
method, your complete Stock
class should now look like this:
class Stock:
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
def cost(self):
return self.shares * self.price
def sell(self, shares):
self.shares -= shares
def __repr__(self):
return f"Stock('{self.name}', {self.shares}, {self.price})"
Now, let's test our modified Stock
class. Open a Python interactive shell by running the following command in your terminal:
python3
Once the interactive shell is open, try the following commands:
>>> import stock
>>> goog = stock.Stock('GOOG', 100, 490.10)
>>> goog
Stock('GOOG', 100, 490.1)
You can also see how the __repr__
method works with a portfolio of stocks. Here's an example:
>>> import reader
>>> portfolio = reader.read_csv_as_instances('portfolio.csv', stock.Stock)
>>> portfolio
[Stock('AA', 100, 32.2), Stock('IBM', 50, 91.1), Stock('CAT', 150, 83.44), Stock('MSFT', 200, 51.23), Stock('GE', 95, 40.37), Stock('MSFT', 50, 65.1), Stock('IBM', 100, 70.44)]
As you can see, the __repr__
method has made our Stock
objects much more informative when displayed in the interactive shell or debugger. It now shows the code needed to recreate each object, which is very useful for debugging and understanding the state of the objects.
When you're done testing, you can exit the Python interpreter by running the following command:
>>> exit()