Differenza tra __str__ e __repr__?


Risposte:


2724

Alex riassunse bene ma, sorprendentemente, era troppo conciso.

Innanzitutto, lasciatemi ripetere i punti principali nel post di Alex :

  • L'implementazione predefinita è inutile (è difficile pensare a uno che non lo sarebbe, ma sì)
  • __repr__ l'obiettivo è quello di essere inequivocabili
  • __str__ l'obiettivo è essere leggibili
  • Il contenitore __str__usa oggetti contenuti '__repr__

L'implementazione predefinita è inutile

Questa è principalmente una sorpresa perché le impostazioni predefinite di Python tendono ad essere abbastanza utili. Tuttavia, in questo caso, avere un valore predefinito per il __repr__quale agirebbe come:

return "%s(%r)" % (self.__class__, self.__dict__)

sarebbe stato troppo pericoloso (per esempio, troppo facile entrare in una ricorsione infinita se gli oggetti si riferissero l'un l'altro). Quindi i poliziotti di Python. Si noti che esiste un valore predefinito che è vero: se __repr__è definito e __str__non lo è, l'oggetto si comporterà come se __str__=__repr__.

Ciò significa, in termini semplici: quasi ogni oggetto che implementate dovrebbe avere un funzionale __repr__utilizzabile per comprendere l'oggetto. L'implementazione __str__è facoltativa: farlo se è necessaria una funzionalità di "stampa carina" (ad esempio, utilizzata da un generatore di report).

L'obiettivo di __repr__è essere inequivocabili

Lasciami uscire e dirlo: non credo nei debugger. Non so davvero come usare alcun debugger e non ne ho mai usato uno sul serio. Inoltre, credo che il grosso difetto dei debugger sia la loro natura di base - la maggior parte degli errori di cui debug ho avuto luogo molto tempo fa, in una galassia molto lontana. Ciò significa che credo, con fervore religioso, nel disboscamento. La registrazione è la linfa vitale di qualsiasi sistema server decente da scartare. Python semplifica la registrazione: con forse alcuni wrapper specifici per il progetto, tutto ciò che serve è un

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

Ma devi fare l'ultimo passo: assicurati che ogni oggetto che implementi abbia un utile repr, quindi un codice del genere può funzionare. Questo è il motivo per cui emerge la cosa "eval": se hai abbastanza informazioni eval(repr(c))==c, significa che sai tutto quello che c'è da sapere c. Se è abbastanza facile, almeno in modo confuso, fallo. In caso contrario, assicurati di disporre di informazioni sufficienti in cogni caso. Io di solito uso un eval-come il formato: "MyClass(this=%r,that=%r)" % (self.this,self.that). Non significa che puoi effettivamente costruire MyClass o che questi sono i giusti argomenti del costruttore - ma è una forma utile per esprimere "questo è tutto ciò che devi sapere su questa istanza".

Nota: ho usato %rsopra, non %s. Vuoi sempre usare repr()[o %rformattare il carattere, in modo equivalente] all'interno __repr__dell'implementazione, o stai sconfiggendo l'obiettivo di repr. Vuoi essere in grado di differenziare MyClass(3)e MyClass("3").

L'obiettivo di __str__è essere leggibili

In particolare, non è da intendersi in modo inequivocabile - notalo str(3)==str("3"). Allo stesso modo, se si implementa un'astrazione IP, avere lo str di come 192.168.1.1 va bene. Quando si implementa un'astrazione di data / ora, lo str può essere "2010/4/12 15:35:22", ecc. L'obiettivo è rappresentarlo in modo che un utente, non un programmatore, vorrebbe leggerlo. Taglia le cifre inutili, fingi di essere un'altra classe - fintanto che supporta la leggibilità, è un miglioramento.

Il contenitore __str__usa oggetti contenuti '__repr__

Questo sembra sorprendente, vero? È un po ', ma quanto sarebbe leggibile se usasse il loro __str__?

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

Non molto. In particolare, le stringhe in un contenitore troverebbero troppo facile disturbarne la rappresentazione. Di fronte all'ambiguità, ricorda, Python resiste alla tentazione di indovinare. Se si desidera il comportamento sopra riportato quando si stampa un elenco, basta

print "[" + ", ".join(l) + "]"

(probabilmente puoi anche capire cosa fare con i dizionari.

Sommario

Implementa __repr__per qualsiasi classe implementata. Questa dovrebbe essere una seconda natura. Implementare __str__se si ritiene che sarebbe utile disporre di una versione di stringa che presenta errori di leggibilità.


154
Decisamente in disaccordo con la tua opinione che il debug non è la strada da percorrere. Per lo sviluppo utilizzare un debugger (e / o registrazione), per la registrazione uso di produzione. Con un debugger hai una visione di tutto ciò che è andato storto quando si è verificato il problema. Puoi vedere il quadro completo. A meno che tu non stia registrando TUTTO, non puoi ottenerlo. Inoltre, se stai registrando tutto ciò che stai per fare, devi guadare tonnellate di dati per ottenere ciò che desideri.
Samuel,

21
Ottima risposta (tranne per il fatto di non usare i debugger). Vorrei solo aggiungere un link a quest'altra domanda e risposta su str vs unicode in Python 3 che potrebbe essere rilevante per la discussione per le persone che hanno effettuato il passaggio.
ThatAintWorking del

11
plus1 per i debugger è inutile e non è degno di un centesimo. Aumenta invece il tuo throughput di registrazione. E sì, questo era un post ben scritto. Si è scoperto che __repr__era quello che mi serviva per il debug. Grazie per l'aiuto.
personal_cloud

7
a parte la tua follia debugger, ho imparato% r e vale comunque la pena votare
Mickey Perlstein il

7
su debugger vs no debugger: non avere opinioni così radicate. In alcune applicazioni il debug non è realistico, in genere quando è coinvolto il tempo reale o quando il codice viene eseguito solo in remoto su una piattaforma con accesso limitato o nessuna console. Nella maggior parte degli altri casi sarà molto più rapido fermarsi a un'eccezione per indagare o impostare un breakpoint, perché non è necessario passare attraverso migliaia di righe di registrazione (che ingombreranno il disco e rallenteranno l'applicazione). Infine, non è sempre possibile accedere, ad esempio su dispositivi integrati, anche il tuo debugger è tuo amico.
RedGlyph

523

La mia regola empirica: __repr__è per gli sviluppatori, __str__è per i clienti.


2
Questo è vero perché per obj = uuid.uuid1 (), obj .__ str __ () è "2d7fc7f0-7706-11e9-94ae-0242ac110002" e obj .__ repr __ () è "UUID ('2d7fc7f0-7706-11e9-94112424 ')". Gli sviluppatori hanno bisogno (valore + origine) mentre i clienti hanno bisogno di un valore e a loro non importa come l'hanno ottenuto!
Naren Yellavula,

1
In questo caso il cliente potrebbe non necessariamente indicare l'utente finale. È il client o l'utente dell'oggetto. Quindi, se si tratta di un SDK, gli sviluppatori SDK useranno in __str__modo che gli sviluppatori normali abbiano un oggetto leggibile. D'altra parte, __repr__è per gli stessi sviluppatori SDK.
Shiplu Mokaddim

398

A meno che non agiate in modo specifico per garantire diversamente, la maggior parte delle classi non ha risultati utili per nessuno dei due:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

Come vedi, nessuna differenza e nessuna informazione oltre la classe e l'oggetto id. Se si ignora solo uno dei due ...:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

come vedi, se esegui l'override __repr__, viene utilizzato ANCHE __str__, ma non viceversa.

Altre curiosità cruciali da sapere: __str__su un contenitore incorporato usa __repr__, NON il __str__, per gli elementi che contiene. E, nonostante le parole sull'argomento che si trovano nei documenti tipici, quasi nessuno si preoccupa di rendere gli __repr__oggetti una stringa che evalpuò essere usata per costruire un oggetto uguale (è troppo difficile, E non sapere come il modulo rilevante sia stato effettivamente importato lo rende effettivamente assolutamente impossibile).

Quindi, il mio consiglio: concentrati sul rendere __str__ragionevolmente leggibile dall'uomo e il __repr__più inequivocabile possibile, anche se ciò interferisce con l'obiettivo sfocato irraggiungibile di rendere __repr__accettabile il valore restituito come input per __eval__!


34
Nei miei test unitari controllo sempre che eval(repr(foo))valuti un oggetto uguale a foo. Hai ragione sul fatto che non funzionerà al di fuori dei miei casi di test poiché non so come sia importato il modulo, ma questo almeno assicura che funzioni in un contesto prevedibile. Penso che sia un buon modo per valutare se il risultato di __repr__è abbastanza esplicito. Fare questo in un test unitario aiuta anche a garantire che __repr__segue le modifiche alla classe.
Steven T. Snyder,

4
Cerco sempre di assicurarmi che eval(repr(spam)) == spam(almeno nel giusto contesto) o eval(repr(spam))sollevi a SyntaxError. In questo modo eviti la confusione. (E questo è quasi vero per i builtin e la maggior parte dello stdlib, ad eccezione di, ad esempio, elenchi ricorsivi, dove a=[]; a.append(a); print(eval(repr(a)))ti dà [[Ellipses]]...) Naturalmente non lo faccio per usare effettivamente eval(repr(spam)), tranne come controllo di sanità mentale nei test unitari ... ma io a volte copia e incolla repr(spam)in una sessione interattiva.
abarnert,

Perché i contenitori (elenchi, tuple) non dovrebbero essere utilizzati __str__per ciascun elemento anziché __repr__? Mi sembra assolutamente sbagliato, dato che ho implementato un leggibile __str__nel mio oggetto e quando fa parte di un elenco vedo __repr__invece il più brutto .
SuperGeo,

Ho appena incontrato un fastidioso bug relativo al fatto che eval(repr(x))fallisce anche per i tipi predefiniti: class A(str, Enum): X = 'x'aumenterà SyntaxError su eval(repr(A.X)). È triste, ma comprensibile. A proposito, in eval(str(A.X))realtà funziona, ma ovviamente solo se class Aè nell'ambito - quindi probabilmente non è molto utile.
massimo

@SuperGeo Altre risposte riguardano questo: container struse element reprbecause [1, 2, 3]! = ["1", "2, 3"].
mtraceur,

163

__repr__: la rappresentazione dell'oggetto Python di solito eval lo convertirà nuovamente in quell'oggetto

__str__: è qualunque cosa tu pensi sia quell'oggetto in forma di testo

per esempio

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True

151

In breve, l'obiettivo di __repr__è essere inequivocabili ed __str__essere leggibili.

Ecco un buon esempio:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

Leggi questa documentazione per repr:

repr(object)

Restituisce una stringa contenente una rappresentazione stampabile di un oggetto. Questo è lo stesso valore prodotto dalle conversioni (virgolette inverse). A volte è utile poter accedere a questa operazione come una normale funzione. 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.

Ecco la documentazione per str:

str(object='')

Restituisce una stringa contenente una rappresentazione ben stampabile di un oggetto. Per le stringhe, questo restituisce la stringa stessa. La differenza repr(object)è che str(object)non sempre si tenta di restituire una stringa accettabile eval(); il suo obiettivo è restituire una stringa stampabile. Se non viene dato alcun argomento, restituisce la stringa vuota, ''.


1
Qual è il significato della stringa stampabile qui? Puoi spiegarlo per favore?
Vicrobot,

115

Qual è la differenza tra __str__e __repr__in Python?

__str__(leggi come "dunder (double-underscore) string") e __repr__(leggi come "dunder-repper" (per "rappresentazione")) sono entrambi metodi speciali che restituiscono stringhe basate sullo stato dell'oggetto.

__repr__fornisce il comportamento di backup se __str__manca.

Quindi si dovrebbe prima scrivere un __repr__che ti permetta di reintegrare un oggetto equivalente dalla stringa che restituisce, ad esempio usando evalo digitando carattere per carattere in una shell Python.

In qualsiasi momento successivo, si può scrivere un __str__per una rappresentazione di stringa leggibile dall'utente dell'istanza, quando si ritiene che sia necessario.

__str__

Se si stampa un oggetto o lo si passa a format, str.formatoppure str, se __str__si definisce un metodo, tale metodo verrà chiamato, altrimenti __repr__verrà utilizzato.

__repr__

Il __repr__metodo viene chiamato dalla funzione builtin repred è ciò che viene ripetuto nella shell di Python quando valuta un'espressione che restituisce un oggetto.

Poiché fornisce un backup per __str__, se solo puoi scriverne uno, inizia con__repr__

Ecco la guida integrata su repr:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

Cioè, per la maggior parte degli oggetti, se si digita ciò che viene stampato repr, si dovrebbe essere in grado di creare un oggetto equivalente. Ma questa non è l'implementazione predefinita.

Implementazione predefinita di __repr__

L'oggetto predefinito __repr__è ( sorgente C Python ) qualcosa del tipo:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

Ciò significa che per impostazione predefinita verrà stampato il modulo da cui proviene l'oggetto, il nome della classe e la rappresentazione esadecimale della sua posizione in memoria, ad esempio:

<__main__.Foo object at 0x7f80665abdd0>

Questa informazione non è molto utile, ma non c'è modo di ricavare come si possa creare accuratamente una rappresentazione canonica di una determinata istanza, ed è meglio di niente, almeno dicendoci come potremmo identificarla in modo univoco nella memoria.

Come può __repr__essere utile?

Diamo un'occhiata a quanto può essere utile, usando la shell e gli datetimeoggetti Python . Per prima cosa dobbiamo importare il datetimemodulo:

import datetime

Se chiamiamo datetime.nownella shell, vedremo tutto ciò di cui abbiamo bisogno per ricreare un oggetto datetime equivalente. Questo è creato dal datetime __repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

Se stampiamo un oggetto datetime, vediamo un bel formato leggibile dall'uomo (in effetti, ISO). Questo è implementato da datetime __str__:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

È semplice ricreare l'oggetto che abbiamo perso perché non l'abbiamo assegnato a una variabile copiandolo e incollandolo __repr__dall'output, quindi stampandolo e ottenendolo nello stesso output leggibile dall'uomo dell'altro oggetto:

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

Come li implemento?

Durante lo sviluppo, ti consigliamo di essere in grado di riprodurre oggetti nello stesso stato, se possibile. Questo, ad esempio, è il modo in cui l'oggetto datetime definisce __repr__( sorgente Python ). È abbastanza complesso, a causa di tutti gli attributi necessari per riprodurre un tale oggetto:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

Se vuoi che il tuo oggetto abbia una rappresentazione più leggibile dall'uomo, puoi implementarlo __str__successivamente. Ecco come implementa l'oggetto datetime ( sorgente Python ) __str__, cosa che fa facilmente perché ha già una funzione per visualizzarlo in formato ISO:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

Impostare __repr__ = __str__?

Questa è una critica di un'altra risposta qui che suggerisce l'impostazione __repr__ = __str__.

L'impostazione __repr__ = __str__è sciocca - __repr__è un fallback per __str__e un __repr__, scritto per l'uso degli sviluppatori nel debug, dovrebbe essere scritto prima di scrivere a __str__.

Ti serve __str__solo quando hai bisogno di una rappresentazione testuale dell'oggetto.

Conclusione

Definisci gli __repr__oggetti che scrivi in ​​modo che tu e altri sviluppatori abbiate un esempio riproducibile quando lo utilizzate mentre lo sviluppate. Definire __str__quando è necessaria una rappresentazione di stringa leggibile dall'uomo.


Non dovrebbe essere qualcosa del genere type(obj).__qualname__?
Solomon Ucko,

@SolomonUcko sì in Python 3, questo sembra essere il caso - ho cercato il codice sorgente in cui questo è implementato e aggiornerò la mia risposta con quelle informazioni quando lo avrò messo insieme.
Aaron Hall

33

A pagina 358 del libro Python scripting for computational science di Hans Petter Langtangen, si afferma chiaramente che

  • L' __repr__obiettivo è una rappresentazione di stringa completa dell'oggetto;
  • Il __str__è quello di restituire una bella stringa per la stampa.

Quindi, preferisco capirli come

  • repr = riprodurre
  • str = string (rappresentazione)

dal punto di vista dell'utente, sebbene questo sia un malinteso che ho fatto durante l'apprendimento del pitone.

Un esempio piccolo ma buono è anche dato sulla stessa pagina come segue:

Esempio

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'

È a pag. # 351.
jiten,

4
È un po 'fuorviante riferirsi a reprriprodurre. È meglio pensarlo come rappresentativo.
Nelson Gon,

31

Oltre a tutte le risposte fornite, vorrei aggiungere alcuni punti: -

1) __repr__()viene richiamato quando scrivi semplicemente il nome dell'oggetto sulla console interattiva di Python e premi Invio.

2) __str__()viene richiamato quando si utilizza l'oggetto con l'istruzione print.

3) Nel caso in cui __str__manchi, quindi stampa e qualsiasi funzione che utilizza str()invoca __repr__()oggetto.

4) __str__()dei contenitori, quando invocato eseguirà il __repr__()metodo dei suoi elementi contenuti.

5) str()chiamato all'interno __str__()potrebbe potenzialmente ricorrere senza un caso base ed errore sulla massima profondità di ricorsione.

6) __repr__()può chiamare repr()che tenterà automaticamente di evitare la ricorsione infinita, sostituendo un oggetto già rappresentato con ....


14

Per dirla semplicemente:

__str__viene utilizzato per mostrare una rappresentazione in forma di stringa dell'oggetto che può essere letta facilmente da altri.

__repr__è usato per mostrare una rappresentazione di stringa del dell'oggetto.

Diciamo che voglio creare una Fractionclasse in cui la rappresentazione in forma di stringa di una frazione sia '(1/2)' e l'oggetto (Classe di frazione) debba essere rappresentato come 'Frazione (1,2)'

Quindi possiamo creare una semplice classe di frazioni:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)

13

In tutta onestà, eval(repr(obj))non viene mai utilizzato. Se ti ritrovi a usarlo, dovresti smettere, perché evalè pericoloso, e le stringhe sono un modo molto inefficiente per serializzare i tuoi oggetti (usa pickleinvece).

Pertanto, consiglierei l'impostazione __repr__ = __str__. Il motivo è che str(list)richiama reprgli elementi (lo considero uno dei maggiori difetti di progettazione di Python che non è stato affrontato da Python 3). Un effettivo reprprobabilmente non sarà molto utile come output di print [your, objects].

Per qualificarlo, nella mia esperienza, il caso d'uso più utile della reprfunzione è inserire una stringa in un'altra stringa (usando la formattazione della stringa). In questo modo, non devi preoccuparti di sfuggire alle citazioni o altro. Ma nota che qui non evalsta succedendo nulla .


19
Penso che questo non vada a buon fine. L'uso di eval(repr(obj))è un test di integrità e una regola empirica - se questo ricrea correttamente l'oggetto originale, allora hai __repr__un'implementazione decente . Non si intende in effetti serializzare gli oggetti in questo modo.
jwg

7
evalnon è intrinsecamente pericoloso. Non è più pericoloso unlink, openo la scrittura di file. Dovremmo smettere di scrivere su file perché forse un attacco malevolo potrebbe usare un percorso di file arbitrario per inserire il contenuto? Tutto è pericoloso se usato stupidamente dalle persone stupide. L'idiozia è pericolosa. Gli effetti Dunning-Kruger sono pericolosi. evalè solo una funzione.
Luis Masuelli,


10

str - Crea un nuovo oggetto stringa dall'oggetto indicato.

repr - Restituisce la rappresentazione di stringa canonica dell'oggetto.

Le differenze:

str ():

  • rende l'oggetto leggibile
  • genera output per l'utente finale

repr ():

  • necessita di codice che riproduca l'oggetto
  • genera output per lo sviluppatore

8

Un aspetto che manca in altre risposte. È vero che in generale lo schema è:

  • Obiettivo __str__: leggibile dall'uomo
  • Obiettivo __repr__: non ambiguo, possibilmente leggibile da una macchina viaeval

Sfortunatamente, questa differenziazione è errata, perché Python REPL e anche IPython usano __repr__per stampare oggetti in una console REPL (vedere le domande correlate per Python e IPython ). Pertanto, i progetti destinati al lavoro con console interattiva (ad esempio Numpy o Pandas) hanno iniziato a ignorare le regole precedenti e forniscono __repr__invece un'implementazione leggibile dall'uomo .


7

Dal libro Fluent Python :

Un requisito di base per un oggetto Python è fornire rappresentazioni di stringhe utilizzabili di se stesso, una utilizzata per il debug e la registrazione, un'altra per la presentazione agli utenti finali. Ecco perché esistono i
metodi speciali __repr__ed __str__esistono nel modello di dati.


5

Le risposte eccellenti coprono già la differenza tra __str__e __repr__, che per me si riduce alla prima che è leggibile anche da un utente finale, e la seconda è il più utile possibile per gli sviluppatori. Detto questo, trovo che l'implementazione predefinita di __repr__spesso non riesca a raggiungere questo obiettivo perché omette informazioni utili agli sviluppatori.

Per questo motivo, se ne ho una abbastanza semplice __str__, in genere cerco solo di ottenere il meglio da entrambi i mondi con qualcosa del tipo:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

4

Una cosa importante da tenere a mente è che gli __str__usi contenuti del container ' __repr__.

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python privilegia l'ambiguità rispetto alla leggibilità , la __str__chiamata di a tuplechiama gli oggetti contenuti ' __repr__, la rappresentazione "formale" di un oggetto. Sebbene la rappresentazione formale sia più difficile da leggere rispetto a quella informale, è inequivocabile e più robusta contro i bug.


Usa __repr__ quando ( __str__) non è definito! Quindi ti sbagli.
jiten,

4

In breve:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'

4
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

Quando print()viene chiamato, decimal.Decimal(23) / decimal.Decimal("1.05")viene stampato il risultato del numero grezzo; questo output è in forma di stringa che può essere ottenuto con __str__(). Se inseriamo semplicemente l'espressione otteniamo un decimal.Decimaloutput: questo output è in forma rappresentativa che può essere raggiunto con __repr__(). Tutti gli oggetti Python hanno due forme di output. La forma di stringa è progettata per essere leggibile dall'uomo. La forma di rappresentazione è progettata per produrre output che se alimentati a un interprete Python (quando possibile) riprodurrebbe l'oggetto rappresentato.


4

__str__può essere invocato su un oggetto chiamando str(obj)e dovrebbe restituire una stringa leggibile dall'uomo.

__repr__può essere invocato su un oggetto chiamando repr(obj)e dovrebbe restituire oggetto interno (campi oggetto / attributi)

Questo esempio può aiutare:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr

3

Comprenderli __str__e __repr__distinguerli in modo intuitivo e permanente.

__str__restituisce il corpo mascherato di una stringa di un determinato oggetto per la leggibilità degli occhi
__repr__restituisce il corpo di carne reale di un determinato oggetto (restituisce se stesso) per l'ambiguità da identificare.

Vedilo in un esempio

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

Quanto a __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

Possiamo eseguire __repr__convenientemente operazioni aritmetiche sui risultati.

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

se applicare l'operazione su __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Restituisce nient'altro che errore.

Un altro esempio.

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

Spero che questo ti aiuti a costruire basi concrete per esplorare più risposte.


3
  1. __str__deve restituire l'oggetto stringa mentre __repr__può restituire qualsiasi espressione python.
  2. Se __str__manca l'implementazione, la __repr__funzione viene utilizzata come fallback. Non esiste alcun fallback se __repr__manca l'implementazione della funzione.
  3. Se la __repr__funzione restituisce la rappresentazione String dell'oggetto, possiamo saltare l'implementazione della __str__funzione.

Fonte: https://www.journaldev.com/22460/python-str-repr-functions


2

__repr__è usato in tutto il mondo, se non per printe strmetodi (quando una __str__è definito!)

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.