Tengo una secuencia de comandos de Python que procesa un archivo .txt que contiene información sobre el uso del informe. Me gustaría encontrar una manera de imprimir de forma limpia los atributos de un objeto utilizando la función pprint (vars (objeto)) de pprint.
El script lee el archivo y crea instancias de una clase de Informe. Aquí está la clase.
class Report(object): def __init__(self, line, headers): self.date_added=get_column_by_header(line,headers,"Date Added") self.user=get_column_by_header(line,headers,"Login ID") self.report=get_column_by_header(line,headers,"Search/Report Description") self.price=get_column_by_header(line,headers,"Price") self.retail_price=get_column_by_header(line,headers,"Retail Price") def __str__(self): from pprint import pprint return str(pprint(vars(self)))
Me gustaría poder imprimir instancias de Report limpiamente a-la-pprint.
for i,line in enumerate(open(path+file_1,'r')): line=line.strip().split("|") if i==0: headers=line if i==1: record=Report(line,headers) print record
Cuando llamo
print record
para una sola instancia de Informe, esto es lo que obtengo en el shell.
{'date_added': '1/3/2012 14:06', 'price': '0', 'report': 'some_report', 'retail_price': '0.25', 'user': 'some_username'} None
Mi pregunta es doble.
Primero, ¿es esta una forma buena / deseada de imprimir los atributos de un objeto de manera limpia? ¿Hay una mejor manera de hacer esto con o sin pprint?
Segundo, porque hace
None
Imprimir en la shell al final? Estoy confundido de donde viene eso.
Gracias por cualquier consejo.
pprint
es sólo otra forma de impresión. Cuando dices pprint(vars(self))
imprime vars en stdout y no devuelve ninguno porque es una función nula. Por lo tanto, cuando lo convierte en una cadena, convierte None
(devuelto por pprint
) en una cadena que luego se imprime desde la statement de impresión inicial. Yo sugeriría cambiar su impresión para pprint
o redefinir impresión como impresión si es todo lo que pprint
.
def __str__(self): from pprint import pprint return str(vars(self)) for i,line in enumerate(open(path+file_1,'r')): line = line.strip().split("|") if i == 0: headers = line if i == 1: record = Report(line,headers) pprint record
Una alternativa es usar una salida formateada:
def __str__(self): return "date added: %s\nPrice: %s\nReport: %s\nretail price: %s\nuser: %s" % tuple([str(i) for i in vars(self).values()])
Espero que esto haya ayudado
La solución de Dan está mal, e Ismail está incompleta.
__str__()
no se llama, __repr__()
se llama. __repr__()
debería devolver una cadena, como lo hace pformat. Aquí hay un ejemplo
class S: def __repr__(self): from pprint import pformat return pformat(vars(self), indent=4, width=1) a = S() ab = 'bee' ac = {'cats': ['blacky', 'tiger'], 'dogs': ['rex', 'king'] } ad = S() admore_c = ac print(a)
Esto imprime
{ 'b': 'bee', 'c': { 'cats': [ 'blacky', 'tiger'], 'dogs': [ 'rex', 'king']}, 'd': { 'more_c': { 'cats': [ 'blacky', 'tiger'], 'dogs': [ 'rex', 'king']}}}
Lo cual no es perfecto, sino pasable.
pprint.pprint
no devuelve una cadena; en realidad realiza la impresión (de forma predeterminada a la salida estándar, pero puede especificar una secuencia de salida). Así que cuando escribe print record
, se llama al record.__str__()
, que llama a pprint
, que devuelve None
. str(None)
es 'None'
, y eso se print
, por lo que no ve None
.
Deberías usar pprint.pformat
en pprint.pformat
lugar. (Alternativamente, puede pasar una instancia de pprint
para pprint
).
Para los objetos de impresión bonita que contienen otros objetos, etc. la pprint
no es suficiente. Intente lib.pretty de IPython , que se basa en un módulo Ruby.
from IPython.lib.pretty import pprint pprint(complex_object)
Creo que beeprint es lo que necesitas.
Simplemente pip install beeprint
y cambie su código a:
def __str__(self): from beeprint import pp return pp(self, output=False)