Mejorando la representación de objetos con __repr__
En Python, los objetos se pueden representar como cadenas de dos maneras diferentes. Estas representaciones tienen diferentes propósitos y son útiles en diversos escenarios.
El primer tipo es la representación como cadena. Esta es creada por la función str()
, que se llama automáticamente cuando se utiliza la función print()
. La representación como cadena está diseñada para ser legible por humanos. Presenta el objeto en un formato que es fácil de entender e interpretar.
El segundo tipo es la representación como código. Esta es generada por la función repr()
. La representación como código muestra el código que se necesitaría escribir para recrear el objeto. Se trata más de proporcionar una forma precisa y sin ambigüedades de representar el objeto en código.
Veamos un ejemplo concreto utilizando la clase date
incorporada en Python. Esto te ayudará a ver la diferencia entre las representaciones como cadena y como código en acción.
>>> from datetime import date
>>> d = date(2008, 7, 5)
>>> print(d) ## Uses str()
2008-07-05
>>> d ## Uses repr()
datetime.date(2008, 7, 5)
En este ejemplo, cuando usamos print(d)
, Python llama a la función str()
en el objeto date
d
, y obtenemos una fecha legible por humanos en el formato YYYY-MM-DD
. Cuando simplemente escribimos d
en la shell interactiva, Python llama a la función repr()
, y vemos el código necesario para recrear el objeto date
.
Puedes obtener explícitamente la cadena de repr()
de varias maneras. Aquí hay algunos ejemplos:
>>> 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)
Ahora, apliquemos este concepto a nuestra clase Stock
. Vamos a mejorar la clase implementando el método __repr__
. Este método especial es llamado por Python cuando necesita la representación como código de un objeto.
Para hacer esto, abre el archivo stock.py
en tu editor. Luego, agrega el método __repr__
a la clase Stock
. El método __repr__
debe devolver una cadena que muestre el código necesario para recrear el objeto Stock
.
def __repr__(self):
return f"Stock('{self.name}', {self.shares}, {self.price})"
Después de agregar el método __repr__
, tu clase Stock
completa debería verse así:
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})"
Ahora, probemos nuestra clase Stock
modificada. Abre una shell interactiva de Python ejecutando el siguiente comando en tu terminal:
python3
Una vez que la shell interactiva esté abierta, prueba los siguientes comandos:
>>> import stock
>>> goog = stock.Stock('GOOG', 100, 490.10)
>>> goog
Stock('GOOG', 100, 490.1)
También puedes ver cómo funciona el método __repr__
con una cartera de acciones. Aquí hay un ejemplo:
>>> 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)]
Como puedes ver, el método __repr__
ha hecho que nuestros objetos Stock
sean mucho más informativos cuando se muestran en la shell interactiva o en el depurador. Ahora muestra el código necesario para recrear cada objeto, lo cual es muy útil para depurar y entender el estado de los objetos.
Cuando hayas terminado de probar, puedes salir del intérprete de Python ejecutando el siguiente comando:
>>> exit()