Come stampare istanze di una classe usando print ()?


539

Sto imparando le corde in Python. Quando provo a stampare un oggetto di classe Foobarusando la print()funzione, ottengo un output come questo:

<__main__.Foobar instance at 0x7ff2a18c>

Esiste un modo per impostare il comportamento di stampa (o la rappresentazione di stringhe ) di una classe e dei suoi oggetti ? Ad esempio, quando chiamo print()un oggetto di classe, vorrei stampare i suoi membri di dati in un determinato formato. Come raggiungere questo obiettivo in Python?

Se hai familiarità con le classi C ++, puoi ottenere quanto sopra per lo standard ostreamaggiungendo un friend ostream& operator << (ostream&, const Foobar&)metodo per la classe.

Risposte:


629
>>> class Test:
...     def __repr__(self):
...         return "Test()"
...     def __str__(self):
...         return "member of Test"
... 
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test

Il __str__metodo è ciò che accade quando lo si stampa e il __repr__metodo è ciò che accade quando si utilizza la repr()funzione (o quando la si guarda con il prompt interattivo). Se questo non è il metodo più Pythonic , mi scuso, perché sto ancora imparando anche io - ma funziona.

Se non __str__viene fornito alcun metodo, Python stamperà invece il risultato __repr__. Se definisci __str__ma non __repr__, Python utilizzerà ciò che vedi sopra come __repr__, ma continuerà a utilizzare __str__per la stampa.


11
c'è anche un metodo unicode , che puoi usare al posto di Str ; si noti che dovrebbe restituire un oggetto unicode, non una stringa (ma se si restituisce una stringa, la conversione in unicode verrà comunque eseguita ...)
kender

@kender - Non lo sapevo, ma a posteriori ha perfettamente senso vista la gestione Unicode rotta di Python 2.x.
Chris Lutz,

11
Penso che questa risposta non possa essere completata senza un link a quest'altra !
tnotstar,

Mi ha salvato! Tuttavia, dopo aver implementato nuovamente il metodo __repr __ (self), print fuorvia gli utenti. Sei a conoscenza di eventuali migliori pratiche in merito?
Viet,

10
Per i programmatori Java: __str __ (self) è come il toString () del mondo python
Janac Meena,

134

Come ha detto Chris Lutz , questo è definito dal __repr__metodo nella tua classe.

Dalla documentazione di repr():

Per molti tipi, questa funzione tenta di restituire una stringa che restituisce un oggetto con lo stesso valore quando viene passata eval(), altrimenti la rappresentazione è una stringa racchiusa tra parentesi angolari che contiene il nome del tipo di oggetto insieme a informazioni aggiuntive spesso includendo il nome e l'indirizzo dell'oggetto. Una classe può controllare ciò che questa funzione restituisce per le sue istanze definendo un __repr__()metodo.

Dato il seguente test di classe:

class Test:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return "<Test a:%s b:%s>" % (self.a, self.b)

    def __str__(self):
        return "From str method of Test: a is %s, b is %s" % (self.a, self.b)

..it agirà nel modo seguente nella shell Python:

>>> t = Test(123, 456)
>>> t
<Test a:123 b:456>
>>> print repr(t)
<Test a:123 b:456>
>>> print(t)
From str method of Test: a is 123, b is 456
>>> print(str(t))
From str method of Test: a is 123, b is 456

Se nessun __str__metodo è definito, print(t)(o print(str(t))) utilizzerà il risultato __repr__invece

Se non __repr__viene definito alcun metodo, viene utilizzato il valore predefinito, che è praticamente equivalente a ..

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))

+1 ma il codice della tua classe __str__è diverso dai risultati della shell interattiva che fornisci. : P
Chris Lutz,

1
Err, oops .. la modifica manuale dell'output REPL non finisce mai bene. Probabilmente dovrei documentare i miei post: P
dbr

1
La %formattazione delle stringhe non è obsoleta, da docs.python.org/whatsnew/2.6.html "l'operatore% è integrato da un metodo di formattazione delle stringhe più potente, format ()"
dbr

4
Dbr: è vero. Si noti che il documento "Novità di Python 3.0" dice anche "metodo format () [...] Il piano è quello di rendere alla fine questa l'unica API per la formattazione delle stringhe e iniziare a deprecare l'operatore% in Python 3.1."
Ashwin Nanjappa,

1
Pitty, %è stato molto conveniente.
Janusz Lenar,

52

Un modo generico che può essere applicato a qualsiasi classe senza una formattazione specifica potrebbe essere fatto come segue:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

E poi,

elem = Element('my_name', 'some_symbol', 3)
print(elem)

produce

__main__.Element: {'symbol': 'some_symbol', 'name': 'my_name', 'number': 3}

23

Se ti trovi in ​​una situazione come @Keith puoi provare:

print a.__dict__

Va contro quello che considererei un buon stile, ma se stai solo cercando di eseguire il debug, dovrebbe fare quello che vuoi.


Sapresti sapere se la chiave dict ha oggetti nei suoi valori?
pranaygoyal02,

1
@HadoopEvangelist Stai chiedendo come stampare in modo ricorsivo anche quegli oggetti o semplicemente determinare se ci sono oggetti?
John,

13

Solo per aggiungere i miei due centesimi alla risposta di @dbr, di seguito è riportato un esempio di come implementare questa frase dalla documentazione ufficiale che ha citato:

"[...] per restituire una stringa che restituirebbe un oggetto con lo stesso valore quando viene passato a eval (), [...]"

Data questa definizione di classe:

class Test(object):
    def __init__(self, a, b):
        self._a = a
        self._b = b

    def __str__(self):
        return "An instance of class Test with state: a=%s b=%s" % (self._a, self._b)

    def __repr__(self):
        return 'Test("%s","%s")' % (self._a, self._b)

Ora è facile serializzare un'istanza di Testclasse:

x = Test('hello', 'world')
print 'Human readable: ', str(x)
print 'Object representation: ', repr(x)
print

y = eval(repr(x))
print 'Human readable: ', str(y)
print 'Object representation: ', repr(y)
print

Quindi, eseguendo l'ultimo pezzo di codice, otterremo:

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Ma, come ho detto nel mio ultimo commento: maggiori informazioni sono qui !


12

È necessario utilizzare __repr__. Questa è una funzione standard come __init__. Per esempio:

class Foobar():
    """This will create Foobar type object."""

    def __init__(self):
        print "Foobar object is created."

    def __repr__(self):
        return "Type what do you want to see here."

a = Foobar()

print a

2
repr e str avere diverse semantica: repr dovrebbe essere fonte Python che sarebbe (ri) creare lo stesso oggetto - questa è la sua repr esentazione in codice; str dovrebbe essere una graziosa stringa di userland dell'oggetto.
Eric Towers,

12

Una versione più carina della risposta di @ user394430

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return  str(self.__class__) + '\n'+ '\n'.join(('{} = {}'.format(item, self.__dict__[item]) for item in self.__dict__))

elem = Element('my_name', 'some_symbol', 3)
print(elem)

Produce un elenco visivamente piacevole di nomi e valori.

<class '__main__.Element'>
name = my_name
symbol = some_symbol
number = 3

Una versione ancora più elaborata (grazie a Ruud) ordina gli articoli:

def __str__(self):
    return  str(self.__class__) + '\n' + '\n'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))

8

Per Python 3:

Se il formato specifico non è importante (ad esempio per il debug) eredita dalla classe stampabile di seguito. Non è necessario scrivere codice per ogni oggetto.

Ispirato da questa risposta

class Printable:
    def __repr__(self):
        from pprint import pformat
        return "<" + type(self).__name__ + "> " + pformat(vars(self), indent=4, width=1)

# Example Usage
class MyClass(Printable):
    pass

my_obj = MyClass()
my_obj.msg = "Hello"
my_obj.number = "46"
print(my_obj)

1

Ci sono già molte risposte in questo thread, ma nessuna di queste mi ha particolarmente aiutato, ho dovuto elaborarlo da solo, quindi spero che questo sia un po 'più informativo.

Devi solo assicurarti di avere le parentesi alla fine della lezione, ad esempio:

print(class())

Ecco un esempio di codice da un progetto a cui stavo lavorando:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number
    def __str__(self):
        return "{}: {}\nAtomic Number: {}\n".format(self.name, self.symbol, self.number

class Hydrogen(Element):
    def __init__(self):
        super().__init__(name = "Hydrogen", symbol = "H", number = "1")

Per stampare la mia classe di idrogeno, ho usato quanto segue:

print(Hydrogen())

Si noti che questo non funzionerà senza le parentesi alla fine dell'idrogeno. Sono necessari.

Spero che questo ti aiuti, fammi sapere se hai altre domande.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.