2012-02-03 6 views
10

Tengo un script de Python que procesa un archivo .txt que contiene información de uso del informe. Me gustaría encontrar una manera de imprimir limpiamente los atributos de un objeto utilizando la función pprint (vars (objeto)) de pprint.Cómo usar pprint para imprimir un objeto usando el método __str __ (self) incorporado?

El script lee el archivo y crea instancias de una clase Report. 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 Reportar 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 del informe, esto es lo que me pasa en la cáscara.

{'date_added': '1/3/2012 14:06', 
'price': '0', 
'report': 'some_report', 
'retail_price': '0.25', 
'user': 'some_username'} 
None 

Mi pregunta es doble.

En primer lugar, ¿es esta una forma buena/deseada de imprimir los atributos de un objeto limpiamente? ¿Hay una mejor manera de hacerlo con o sin impresión?

En segundo lugar, ¿por qué

None 

de impresión a la concha al final? Estoy confundido de dónde viene eso.

Gracias por cualquier consejo.

+1

nota al margen en __str__ cuando se incluye a partir pprint importación pprint, si sólo está utilizando este método una o dos veces, está bien, pero para un método comúnmente utilizado este módulo se importará (de manera computacionalmente intensa) cada vez que se llame al método. Creo que sería mejor tener tus módulos importados en la parte superior. También esto mejora el rendimiento general en las secuencias de comandos de Python. – lukecampbell

+0

@lukecampbell: no es cierto que las importaciones posteriores sean computacionalmente intensivas. Cuando importa, el mecanismo se ve en un dict en sys.modules para ver si ya está cargado. Si es así, no se hace nada más. Solo si nunca se ha importado, el mecanismo de importación hace otra cosa. – bgporter

+0

@bgporter: ¿Qué sucede si crea otra instancia del objeto? –

Respuesta

5

pprint es solo otra forma de impresión. Cuando dice pprint(vars(self)), imprime vars en stdout y no devuelve ninguno porque es una función vacía. Por lo tanto, cuando lo lances en una cadena, se convierte en None (devuelto por pprint) en una cadena que luego se imprime desde la instrucción de impresión inicial. Sugeriría cambiar su impresión al pprint o redefinir la impresión como impresión si es todo lo que usa.

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 utilizar un formato de salida:

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 ayudó

+1

Mientras ha diagnosticado correctamente la falla, las soluciones sugeridas son bastante torpes; pprint.pformat es mucho más elegante. – Symmetric

11

pprint.pprint no devuelve una cadena; en realidad realiza la impresión (por defecto es stdout, pero puede especificar una secuencia de salida). Por lo tanto, cuando escribe print record, se llama a record.__str__(), que llama al pprint, que devuelve None. str(None) es 'None', y eso obtiene print ed, por eso usted ve None.

En su lugar, debe usar pprint.pformat. (Alternativamente, puede pasar una instancia StringIO a pprint.)

3

Para los objetos de impresión legible que contienen otros objetos, etc. pprint no es suficiente. Pruebe IPython's lib.pretty, que se basa en un módulo de Ruby.

from IPython.lib.pretty import pprint 
pprint(complex_object) 
11

solución de Dan es simplemente incorrecto, e Ismail en la incompleta.

  1. __str__() no se llama, __repr__() se llama.
  2. __repr__() debe devolver una cadena, como lo hace pformat.
  3. imprimir normalmente sangra solo 1 carácter e intenta guardar líneas. Si está tratando de descubrir la estructura, establezca el ancho bajo y sangría alto.

Aquí es un ejemplo

class S: 
    def __repr__(self): 
     from pprint import pformat 
     return pformat(vars(self), indent=4, width=1) 

a = S() 
a.b = 'bee' 
a.c = {'cats': ['blacky', 'tiger'], 'dogs': ['rex', 'king'] } 
a.d = S() 
a.d.more_c = a.c 

print(a) 

Esto imprime

{ 'b': 'bee', 
    'c': { 'cats': [ 'blacky', 
         'tiger'], 
      'dogs': [ 'rex', 
         'king']}, 
    'd': { 'more_c': { 'cats': [ 'blacky', 
           'tiger'], 
        'dogs': [ 'rex', 
           'king']}}} 

que no es perfecto, pero pasable.

3

Creo que beeprint es lo que necesita.

Sólo pip install beeprint y cambiar el código para:

def __str__(self): 
    from beeprint import pp 
    return pp(self, output=False) 
Cuestiones relacionadas