python example __add__ - Unterschied zwischen __str__ und __repr__?



10 Answers

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

vs how to

Was ist der Unterschied zwischen __str__ und __repr__ in Python ?




__repr__ : Die Darstellung eines Python-Objekts konvertiert es normalerweise in dieses Objekt zurück

__str__ : ist das, was Sie als Objekt in Textform halten

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



Was ist der Unterschied zwischen __str__ und __repr__ in Python?

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

__repr__ gibt das Sicherungsverhalten an, wenn __str__ fehlt.

Daher sollte man zuerst ein __repr__ schreiben, mit dem ein äquivalentes Objekt aus der zurückgegebenen Zeichenfolge __repr__ kann, z. B. mit eval oder durch Eingabe von Zeichen für Zeichen in einer Python-Shell.

Zu einem späteren Zeitpunkt kann ein __str__ für eine vom Benutzer lesbare Zeichenfolgendarstellung der Instanz geschrieben werden, wenn dies als notwendig erachtet wird.

__str__

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

__repr__

Die __repr__ Methode wird von der eingebauten Funktion repr aufgerufen und wird in Ihrer Python-Shell angezeigt, wenn sie einen Ausdruck auswertet, der ein Objekt zurückgibt.

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

Hier ist die eingebaute Hilfe zu repr :

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

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

Das heißt, für die meisten Objekte sollten Sie in der Lage sein, ein gleichwertiges Objekt zu erstellen, wenn Sie repr , was von repr gedruckt wird. Dies ist jedoch nicht die Standardimplementierung.

Standardimplementierung von __repr__

Das Standardobjekt __repr__ lautet ( C-Python-Quelle ), etwa wie __repr__ :

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 drucken, aus dem sich das Objekt befindet, den Klassennamen und die hexadezimale Darstellung des Speicherorts im Speicher, z. B .:

<__main__.Foo object at 0x7f80665abdd0>

Diese Informationen sind nicht sehr nützlich, aber man kann nicht ableiten, wie man eine kanonische Repräsentation einer bestimmten Instanz genau erzeugen kann, und es ist besser als nichts, zumindest uns zu sagen, wie wir sie im Speicher eindeutig identifizieren können.

Wie kann __repr__ nützlich sein?

Schauen wir uns an, wie nützlich es ist, wenn man die Python-Shell und die datetime Objekte verwendet. Zuerst müssen wir das datetime Modul importieren:

import datetime

Wenn wir datetime.now in der Shell aufrufen, sehen wir alles, was wir benötigen, um ein entsprechendes datetime-Objekt neu zu erstellen. Dies wird durch die Datumszeit __repr__ :

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

Wenn wir ein datetime-Objekt drucken, sehen wir ein schönes, vom Menschen lesbares Format (tatsächlich ISO). Dies wird durch __str__ von datetime __str__ :

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

Es ist eine einfache Sache, das verlorene Objekt neu zu erstellen, weil wir es keiner Variablen zugewiesen haben, indem es aus der __repr__ Ausgabe kopiert und __repr__ wurde. Anschließend wurde es gedruckt, und wir erhalten es in derselben vom Menschen lesbaren Ausgabe wie das andere Objekt:

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

Bei der Entwicklung sollten Sie Objekte möglichst im gleichen Zustand reproduzieren können. So definiert das datetime-Objekt beispielsweise __repr__ ( Python-Quelle ). Es ist ziemlich komplex, da alle Attribute zur Wiedergabe eines solchen Objekts erforderlich sind:

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 besser lesbar ist, können __str__ Nächstes __str__ implementieren. Das datetime-Objekt ( Python-Quelle ) implementiert __str__ ist einfach möglich, da es bereits über eine Funktion zur Anzeige im ISO-Format verfügt:

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

Setze __repr__ = __str__ ?

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

Die Einstellung __repr__ = __str__ ist dumm - __repr__ ist ein Fallback für __str__ und ein __repr__ , das für Entwickler in Debugging- __repr__ geschrieben wurde, sollte vor dem Schreiben eines __str__ .

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

Fazit

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




Auf Seite 358 des Buches Python-Scripting für Computerwissenschaft von Hans Petter Langtangen heißt es klar

  • Das __repr__ zielt auf eine vollständige Darstellung des Objekts in einer Zeichenkette.
  • Die __str__ gibt eine __str__ Zeichenfolge zum Drucken zurück.

Ich bevorzuge es, sie als zu verstehen

  • repr = reproduzieren
  • str = string (Darstellung)

Aus der Sicht des Benutzers, obwohl dies ein Missverständnis ist, das ich beim Lernen von Python gemacht habe.

Ein kleines, aber gutes Beispiel wird auf derselben Seite wie folgt gegeben:

Beispiel

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'



Einfach gesagt:

__str__ wird verwendet, um eine Zeichenfolgendarstellung Ihres Objekts __str__ , die von anderen leicht gelesen werden kann .

__repr__ wird verwendet, um eine Zeichenfolgendarstellung des Objekts __repr__ .

Nehmen wir an, ich möchte eine Fraction Klasse erstellen, bei der die Zeichenfolgendarstellung eines Bruchs '(1/2)' ist und das Objekt (Fraction-Klasse) als 'Fraction (1,2)' dargestellt werden soll.

So können wir eine einfache Fraktionsklasse erstellen:

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)



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

  • Ziel von __str__ : für Menschen lesbar
  • Ziel von __repr__ : eindeutig, evtl. maschinenlesbar

Leider ist diese Unterscheidung fehlerhaft, da Python REPL und auch IPython __repr__ für das 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), damit begonnen, die obigen Regeln zu ignorieren und stattdessen eine von Menschen lesbare __repr__ Implementierung __repr__ .




"A basic requirement for a Python object is to provide usable 
 string   representations of itself, one used for debugging and
 logging, another for presentation to end users. That is why the  
 special methods __repr__ and __str__ exist in the data model."

Aus dem Buch: Fließender Python




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

Wenn print () nach dem Ergebnis von decimal.Decimal (23) / decimal.Decimal ("1.05") aufgerufen wird, wird die Rohzahl gedruckt. Diese Ausgabe erfolgt in einer String-Form, die mit __str __ () erreicht werden kann. Wenn wir einfach den Ausdruck eingeben, erhalten wir eine dezimale.Decimal-Ausgabe - diese Ausgabe hat eine repräsentative Form, die mit __repr __ () erreicht werden kann. Alle Python-Objekte haben zwei Ausgabeformen. Die String-Form ist für Menschen lesbar. Die Darstellungsform soll eine Ausgabe erzeugen, die, wenn sie einem Python-Interpreter zugeführt wird, (wenn möglich) das dargestellte Objekt erneut erzeugen würde




So viel klarer aus dem blog

str ist wie toString. erstellt, so dass Sie die Daten drucken können, wie Serialisierung oder Pickle. Wie kann ich dieses Objekt neu erstellen, 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))



__str__ und __repr__ intuitiv und dauerhaft zu verstehen.

__str__ den als Zeichenfolge getarnten Körper eines gegebenen Objekts für die Lesbarkeit der Augen zurück
__repr__ den realen Fleischkörper eines gegebenen Objekts zurückgeben (selbst zurückgeben), um die Eindeutigkeit zu identifizieren.

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 arithmetische Operationen mit __repr__ Ergebnissen 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 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 nur 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 dabei, konkrete Gründe zu finden, um weitere Antworten zu finden.




Related