Risposte:
Alex riassunse bene ma, sorprendentemente, era troppo conciso.
Innanzitutto, lasciatemi ripetere i punti principali nel post di Alex :
__repr__
l'obiettivo è quello di essere inequivocabili__str__
l'obiettivo è essere leggibili__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 c
ogni 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 %r
sopra, non %s
. Vuoi sempre usare repr()
[o %r
formattare 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à.
__repr__
era quello che mi serviva per il debug. Grazie per l'aiuto.
La mia regola empirica: __repr__
è per gli sviluppatori, __str__
è per i clienti.
__str__
modo che gli sviluppatori normali abbiano un oggetto leggibile. D'altra parte, __repr__
è per gli stessi sviluppatori SDK.
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 eval
può 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__
!
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.
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.
__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 .
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.
str
use element repr
because [1, 2, 3]
! = ["1", "2, 3"]
.
__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
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)
è chestr(object)
non sempre si tenta di restituire una stringa accettabileeval()
; il suo obiettivo è restituire una stringa stampabile. Se non viene dato alcun argomento, restituisce la stringa vuota,''
.
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 eval
o 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.format
oppure str
, se __str__
si definisce un metodo, tale metodo verrà chiamato, altrimenti __repr__
verrà utilizzato.
__repr__
Il __repr__
metodo viene chiamato dalla funzione builtin repr
ed è 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.
__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.
__repr__
essere utile?Diamo un'occhiata a quanto può essere utile, usando la shell e gli datetime
oggetti Python . Per prima cosa dobbiamo importare il datetime
modulo:
import datetime
Se chiamiamo datetime.now
nella 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
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=' ')
__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.
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.
type(obj).__qualname__
?
A pagina 358 del libro Python scripting for computational science di Hans Petter Langtangen, si afferma chiaramente che
__repr__
obiettivo è una rappresentazione di stringa completa dell'oggetto;__str__
è quello di restituire una bella stringa per la stampa.Quindi, preferisco capirli come
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:
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'
repr
riprodurre. È meglio pensarlo come rappresentativo.
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 ...
.
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 Fraction
classe 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)
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 pickle
invece).
Pertanto, consiglierei l'impostazione __repr__ = __str__
. Il motivo è che str(list)
richiama repr
gli elementi (lo considero uno dei maggiori difetti di progettazione di Python che non è stato affrontato da Python 3). Un effettivo repr
probabilmente non sarà molto utile come output di print [your, objects]
.
Per qualificarlo, nella mia esperienza, il caso d'uso più utile della repr
funzione è 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 eval
sta succedendo nulla .
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.
eval
non è intrinsecamente pericoloso. Non è più pericoloso unlink
, open
o 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.
Da un (An Unofficial) Python Reference Wiki (copia dell'archivio) di effbot:
__str__
" calcola la rappresentazione di stringa" informale "di un oggetto. Ciò differisce dal fatto __repr__
che non deve essere un'espressione Python valida: al suo posto può essere usata una rappresentazione più comoda o concisa. "
__repr__
non è affatto richiesto per restituire un'espressione Pailon vaild.
str
- Crea un nuovo oggetto stringa dall'oggetto indicato.
repr
- Restituisce la rappresentazione di stringa canonica dell'oggetto.
Le differenze:
str ():
repr ():
Un aspetto che manca in altre risposte. È vero che in generale lo schema è:
__str__
: leggibile dall'uomo__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 .
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.
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))
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 tuple
chiama 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.
__repr__
quando ( __str__
) non è definito! Quindi ti sbagli.
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'
>>> 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.Decimal
output: 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.
__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
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.
__str__
deve restituire l'oggetto stringa mentre __repr__
può restituire qualsiasi espressione python.__str__
manca l'implementazione, la __repr__
funzione viene utilizzata come fallback. Non esiste alcun fallback se __repr__
manca l'implementazione della funzione.__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