[python] Unterschied zwischen __str__ und __repr__?



Answers

Meine Faustregel: __repr__ ist für Entwickler, __str__ ist für Kunden.

Question

Was ist der Unterschied zwischen __str__ und __repr__ in Python ?




Abgesehen von allen gegebenen Antworten möchte ich einige Punkte hinzufügen:

1) __str__() wird aufgerufen, wenn Sie ein Objekt mit print-Anweisung verwenden. Wenn __str__ fehlt, ruft print __repr__() des Objekts auf.

2) __repr__() wird aufgerufen, wenn Sie den Namen des Objekts einfach in die interaktive Python-Konsole schreiben und die Eingabetaste drücken.

3) __str__() von Containern, wenn aufgerufen, __repr__() -Methode seiner enthaltenen Elemente ausführen.




Von http://pyref.infogami.com/__str__ von effbot:

__str__ "berechnet die" informelle "Zeichenfolgendarstellung eines Objekts. Dies unterscheidet sich von __repr__ dass es kein gültiger Python-Ausdruck sein muss: stattdessen kann eine bequemere oder prägnantere Darstellung verwendet werden."




Eine wichtige Sache zu beachten ist, dass Container __str__ die enthaltenen Objekte __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 favorisiert Eindeutigkeit gegenüber Lesbarkeit , der __str__ Aufruf eines tuple ruft die enthaltenen Objekte __repr__ , die "formale" Darstellung eines Objekts, auf. Obwohl die formale Darstellung schwieriger zu lesen ist als eine informelle, ist sie unmissverständlich und robuster gegen Bugs.




Ausgezeichnete Antworten decken bereits den Unterschied zwischen __str__ und __repr__ , was für mich darauf __repr__ , dass die __str__ __repr__ auch für einen Endbenutzer lesbar ist und letztere für Entwickler so nützlich wie möglich ist. In Anbetracht dessen finde ich, dass die Standardimplementierung von __repr__ dieses Ziel oft nicht erreicht, weil sie für Entwickler nützliche Informationen weglässt .

Aus diesem Grund versuche ich, wenn ich einfach genug __str__ , einfach das Beste aus beiden Welten zu bekommen mit:

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



__repr__ : Repräsentation des Python-Objekts eval konvertiert es normalerweise zurück in das Objekt

__str__ : was immer du denkst, ist das Objekt in Textform

z.B

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



Verstehen Sie __str__ und __repr__ intuitiv und dauerhaft überhaupt.

__str__ den __str__ eines bestimmten Objekts für lesbare Augen zurück
__repr__ den realen fleischlichen Körper eines gegebenen Objekts zurückgeben (sich selbst zurückgeben), um die Eindeutigkeit zu erkennen.

Sehen Sie es in einem Beispiel

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

Zu __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.

Wir können die arithmetische Operation auf __repr__ Ergebnisse bequem durchführen.

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)

wenn Sie die Operation auf __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'

Gibt nichts als einen Fehler zurück.

Ein anderes Beispiel.

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

Ich hoffe, dies hilft Ihnen, konkrete Gründe zu schaffen, um mehr Antworten zu finden.




So viel klarer aus dem blog

str ist wieString. erstellt, damit Sie die Daten drucken können, ist wie Serialisieren oder Gurken. Wie erstelle ich dieses Objekt neu, wenn ich dies mit eval () tun muss

>>> import datetime
>>> now = datetime.datetime.now() 
>>> str(now)
'2015-04-04 20:51:31.766862'
>>> repr(now)
'datetime.datetime(2015, 4, 4, 20, 51, 31, 766862)'
>>mydate = eval(repr(now))



Ein Aspekt, der in anderen Antworten fehlt. Es stimmt, dass das Muster im Allgemeinen ist:

  • Ziel von __str__ : menschenlesbar
  • Ziel von __repr__ : eindeutig, möglicherweise über eval maschinenlesbar

Leider ist diese Unterscheidung fehlerhaft, da Python REPL und auch IPython __repr__ zum Drucken von Objekten in einer REPL-Konsole verwenden (siehe verwandte Fragen zu Python und IPython ). Daher haben Projekte, die auf interaktive Konsolenarbeit abzielen (z. B. Numpy oder Pandas), begonnen, obige Regeln zu ignorieren und stattdessen eine menschlich lesbare __repr__ Implementierung __repr__ .




Was ist der Unterschied zwischen __str__ und __repr__ in Python?

__str__ (gelesen als "dunder (doppelter Unterstrich)") und __repr__ (gelesen als "dunder-repper" (für "Repräsentation")) sind beide spezielle Methoden, die Strings basierend auf dem Zustand des Objekts zurückgeben.

__repr__ bietet Backup-Verhalten, wenn __str__ fehlt.

Man sollte also zuerst einen __repr__ schreiben, der es erlaubt, ein äquivalentes Objekt aus der zurückgegebenen Zeichenkette __repr__ , zB mit eval oder indem man es zeichenweise in eine Python-Shell eingibt.

Zu einem späteren Zeitpunkt kann man ein __str__ für eine benutzerlesbare String-Repräsentation der Instanz schreiben, wenn man es für notwendig hält.

__str__

Wenn Sie ein Objekt drucken oder es an format , str.format oder str , wird diese Methode aufgerufen, wenn eine Methode __str__ definiert ist, andernfalls wird __repr__ verwendet.

__repr__

Die Methode __repr__ wird von der eingebauten Funktion repr aufgerufen und wird in der Python-Shell zurückgegeben, wenn ein Ausdruck ausgewertet wird, der ein Objekt zurückgibt.

Da es eine Sicherung für __str__ bietet, wenn Sie nur eine schreiben können, beginnen Sie mit __repr__

Hier ist die eingebaute Hilfe zum Rep:

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

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

Das heißt, wenn Sie bei den meisten Objekten repr , was von repr gedruckt wird, sollten Sie in der Lage sein, ein äquivalentes Objekt zu erstellen. Dies ist jedoch nicht die Standardimplementierung.

Standardimplementierung von __repr__

Das Standardobjekt __repr__ ist ( C Python-Quelle ) etwas wie:

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

Das bedeutet, dass Sie standardmäßig das Modul, aus dem das Objekt besteht, den Klassennamen und die hexadezimale Darstellung seiner Position im Speicher ausgeben. Beispiel:

<__main__.Foo object at 0x7f80665abdd0>

Diese Information ist nicht sehr nützlich, aber es gibt keine Möglichkeit, abzuleiten, wie man eine kanonische Repräsentation einer bestimmten Instanz genau erstellen könnte, und es ist besser als nichts, und sagt uns zumindest, wie wir es im Gedächtnis eindeutig identifizieren können.

Wie kann __repr__ nützlich sein?

Sehen wir uns an, wie nützlich es sein kann, wenn wir die Python-Shell und datetime Objekte verwenden. Zuerst müssen wir das datetime Modul importieren:

import datetime

Wenn wir datetime.now in der Shell aufrufen, sehen wir alles, was wir brauchen, um ein äquivalentes Datetime-Objekt zu erzeugen. Dies wird durch datetime __repr__ :

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

Wenn wir ein Datetime-Objekt drucken, sehen wir ein nettes, vom Menschen lesbares (eigentlich ISO) Format. Dies wird durch __str__ von datetime __str__ :

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

Es ist einfach, das verloren gegangene Objekt neu zu erstellen, weil wir es nicht einer Variablen zugewiesen haben, indem wir es aus der __repr__ Ausgabe kopiert und __repr__ haben und es dann in der gleichen lesbaren Ausgabe wie das andere Objekt ausgegeben haben:

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

Wie implementiere ich sie?

Während Sie sich entwickeln, sollten Sie in der Lage sein, Objekte möglichst in demselben Zustand zu reproduzieren. Dies ist zum Beispiel, wie das Datetime-Objekt __repr__ ( Python-Quelle ) definiert. Es ist ziemlich komplex, wegen all der Attribute, die benötigt werden, um ein solches Objekt zu reproduzieren:

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 = ", ".join(map(str, L))
    s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    return s

Wenn Sie möchten, dass Ihr Objekt eine besser lesbare Darstellung hat, können Sie __str__ next implementieren. Das Datetime-Objekt ( Python-Quelle ) implementiert __str__ , was leicht gemacht wird, da es bereits eine Funktion zur Anzeige im ISO-Format hat:

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

Setze __repr__ = __str__ ?

Dies ist eine Kritik einer anderen Antwort hier, die die Einstellung __repr__ = __str__ .

Die Einstellung __repr__ = __str__ ist dumm - __repr__ ist ein Fallback für __str__ und ein __repr__ , geschrieben für die Verwendung der Entwickler im Debugging, sollte geschrieben werden, bevor Sie ein __str__ schreiben.

Sie benötigen ein __str__ nur, wenn Sie eine textuelle Darstellung des Objekts benötigen.

Fazit

Definieren Sie __repr__ für Objekte, die Sie schreiben, damit Sie und andere Entwickler ein reproduzierbares Beispiel haben, wenn Sie es bei der Entwicklung verwenden. Definieren Sie __str__ wenn Sie eine für Menschen lesbare Zeichenfolgendarstellung davon benötigen.






Related