Unterschied zwischen __str__ und __repr__?

Antworten:

2723

Alex fasste gut zusammen, war aber überraschenderweise zu prägnant.

Lassen Sie mich zunächst die wichtigsten Punkte in Alex 'Beitrag wiederholen :

  • Die Standardimplementierung ist nutzlos (es ist schwer, sich eine vorzustellen, die es nicht wäre, aber ja)
  • __repr__ Ziel ist es, eindeutig zu sein
  • __str__ Ziel ist es, lesbar zu sein
  • Container __str__verwendet enthaltene Objekte '__repr__

Die Standardimplementierung ist nutzlos

Dies ist meistens eine Überraschung, da die Standardeinstellungen von Python in der Regel ziemlich nützlich sind. In diesem Fall hätte ein Standardwert __repr__jedoch Folgendes:

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

wäre zu gefährlich gewesen (zum Beispiel zu leicht, um in eine unendliche Rekursion zu geraten, wenn Objekte aufeinander verweisen). Also macht Python Schluss. Beachten Sie, dass es einen Standard gibt, der wahr ist: Wenn __repr__definiert ist und __str__nicht, verhält sich das Objekt so, als ob __str__=__repr__.

Dies bedeutet in einfachen Worten: Fast jedes Objekt, das Sie implementieren, sollte über eine Funktion verfügen __repr__, die zum Verständnis des Objekts verwendet werden kann. Die Implementierung __str__ist optional: Tun Sie dies, wenn Sie eine "Pretty Print" -Funktion benötigen (z. B. von einem Berichtsgenerator verwendet).

Das Ziel von __repr__ist es, eindeutig zu sein

Lassen Sie mich gleich herauskommen und es sagen - ich glaube nicht an Debugger. Ich weiß nicht wirklich, wie man einen Debugger benutzt, und habe noch nie einen ernsthaft benutzt. Darüber hinaus glaube ich, dass der große Fehler bei Debuggern ihre grundlegende Natur ist - die meisten Fehler, die ich debugge, sind vor langer, langer Zeit in einer weit entfernten Galaxie aufgetreten. Dies bedeutet, dass ich mit religiösem Eifer an die Protokollierung glaube. Die Protokollierung ist das Lebenselixier eines anständigen Fire-and-Forget-Serversystems. Python erleichtert die Protokollierung: Mit einigen projektspezifischen Wrappern benötigen Sie lediglich eine

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)

Aber Sie müssen den letzten Schritt tun - stellen Sie sicher, dass jedes Objekt, das Sie implementieren, einen nützlichen Repräsentanten hat, damit Code wie dieser einfach funktionieren kann. Aus diesem Grund taucht die „Eval“ -Sache auf: Wenn Sie über genügend Informationen verfügen eval(repr(c))==c, bedeutet dies , dass Sie alles wissen, was Sie wissen müssen c. Wenn das einfach genug ist, zumindest auf unscharfe Weise, tun Sie es. Wenn nicht, stellen Sie sicher, dass Sie über genügend Informationen verfügen c. Normalerweise verwende ich ein eval-ähnliches Format : "MyClass(this=%r,that=%r)" % (self.this,self.that). Dies bedeutet nicht, dass Sie MyClass tatsächlich erstellen können oder dass dies die richtigen Konstruktorargumente sind. Es ist jedoch eine nützliche Form, um auszudrücken, dass dies alles ist, was Sie über diese Instanz wissen müssen.

Hinweis: Ich habe %roben nicht verwendet %s. Sie möchten immer repr()[oder %rgleichwertiges Formatieren von Zeichen] in der __repr__Implementierung verwenden, oder Sie vereiteln das Ziel von repr. Sie wollen unterscheiden können MyClass(3)und MyClass("3").

Ziel __str__ist es, lesbar zu sein

Insbesondere soll es nicht eindeutig sein - beachten Sie das str(3)==str("3"). Wenn Sie eine IP-Abstraktion implementieren, ist es ebenfalls in Ordnung, wenn die Str wie 192.168.1.1 aussieht. Bei der Implementierung einer Datums- / Zeitabstraktion kann der Str "2010/4/12 15:35:22" usw. sein. Ziel ist es, ihn so darzustellen, dass ein Benutzer, kein Programmierer, ihn lesen möchte. Hacken Sie nutzlose Ziffern ab und geben Sie vor, eine andere Klasse zu sein - solange sie die Lesbarkeit unterstützt, ist dies eine Verbesserung.

Container __str__verwendet enthaltene Objekte '__repr__

Das scheint überraschend, nicht wahr? Es ist ein wenig, aber wie lesbar wäre es, wenn es ihre verwendet __str__?

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

Nicht sehr. Insbesondere die Zeichenfolgen in einem Container würden es viel zu leicht finden, seine Zeichenfolgendarstellung zu stören. Denken Sie daran, dass Python angesichts der Zweideutigkeit der Versuchung widersteht, zu raten. Wenn Sie das obige Verhalten beim Drucken einer Liste wünschen, einfach

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

(Sie können wahrscheinlich auch herausfinden, was Sie mit Wörterbüchern tun sollen.

Zusammenfassung

Implementieren Sie __repr__für jede Klasse, die Sie implementieren. Dies sollte eine zweite Natur sein. Implementieren __str__Sie, wenn Sie der Meinung sind, dass es nützlich wäre, eine String-Version zu haben, die sich auf der Seite der Lesbarkeit irrt.

Moshez
quelle
154
Stimmen Sie Ihrer Meinung definitiv nicht zu, dass das Debuggen nicht der richtige Weg ist. Verwenden Sie für die Entwicklung einen Debugger (und / oder eine Protokollierung), für die Produktion die Protokollierung. Mit einem Debugger haben Sie einen Überblick über alles, was beim Auftreten des Problems schief gelaufen ist. Sie können das ganze Bild sehen. Wenn Sie nicht ALLES protokollieren, können Sie das nicht bekommen. Wenn Sie alles protokollieren, müssen Sie Tonnen von Daten durchsuchen, um das zu erreichen, was Sie wollen.
Samuel
21
Tolle Antwort (mit Ausnahme der Tatsache, dass keine Debugger verwendet werden). Ich möchte nur einen Link zu dieser anderen Frage und Antwort zu str vs unicode in Python 3 hinzufügen , der für die Diskussion für Personen relevant sein könnte, die den Wechsel vorgenommen haben.
ThatAintWorking
11
plus1 für Debugger sind nutzlos und skalieren keinen Cent wert. Erhöhen Sie stattdessen Ihren Protokollierungsdurchsatz. Und ja, das war ein gut geschriebener Beitrag. Es stellte sich heraus, __repr__was ich zum Debuggen brauchte. Danke für deine Hilfe.
personal_cloud
7
Abgesehen von Ihrer Debugger-Torheit habe ich das% r gelernt und das ist sowieso die Abstimmung wert
Mickey Perlstein
6
on debugger vs no debugger: Erhalten Sie keine so tief verwurzelten Meinungen. In einigen Anwendungen ist das Debuggen nicht realistisch, normalerweise wenn es um Echtzeit geht oder wenn Ihr Code nur remote auf einer Plattform mit wenig Zugriff oder ohne Konsole ausgeführt wird. In den meisten anderen Fällen ist es viel schneller, bei einer Ausnahme anzuhalten, um Nachforschungen anzustellen oder einen Haltepunkt festzulegen, da Sie nicht Tausende von Protokollierungszeilen durchlaufen müssen (was Ihre Festplatte überladen und die Anwendung verlangsamen wird). Schließlich ist es nicht immer möglich, sich beispielsweise auf eingebetteten Geräten anzumelden. Dort ist der Debugger auch Ihr Freund.
RedGlyph
523

Meine Faustregel: __repr__ist für Entwickler, __str__ist für Kunden.

Ned Batchelder
quelle
2
Dies ist richtig, weil für obj = uuid.uuid1 () obj .__ str __ () "2d7fc7f0-7706-11e9-94ae-0242ac110002" und obj .__ repr __ () "UUID ('2d7fc7f0-7706-11e9-94ae-0242ac110002) ist ') ". Entwickler brauchen (Wert + Herkunft), während Kunden einen Wert brauchen und es ihnen egal ist, wie sie ihn bekommen haben!
Naren Yellavula
1
Hier muss Kunde nicht unbedingt Endbenutzer bedeuten. Es ist der Client oder Benutzer des Objekts. Wenn es sich also um ein SDK handelt, verwenden die SDK-Entwickler, __str__sodass normale Entwickler lesbare Objekte haben. Auf der anderen Seite __repr__ist für die SDK-Entwickler selbst.
Shiplu Mokaddim
398

Sofern Sie nicht ausdrücklich etwas anderes tun, haben die meisten Klassen auch keine hilfreichen Ergebnisse für:

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

Wie Sie sehen - kein Unterschied und keine Informationen über die Klasse und das Objekt hinaus id. Wenn Sie nur einen der beiden überschreiben ...:

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

Wie Sie sehen, wenn Sie überschreiben __repr__, wird dies AUCH verwendet __str__, aber nicht umgekehrt.

Weitere wichtige Leckerbissen: Bei __str__einem eingebauten Container wird das __repr__, NICHT das __str__, für die darin enthaltenen Elemente verwendet. Und trotz der Wörter zu diesem Thema, die in typischen Dokumenten zu finden sind, stört es kaum jemanden, die __repr__Objekte zu einer Zeichenfolge evalzu machen, mit der ein gleiches Objekt erstellt werden kann (es ist einfach zu schwierig, und wenn man nicht weiß, wie das relevante Modul tatsächlich importiert wurde, ist dies tatsächlich der Fall rundum unmöglich).

Also, mein Rat: Konzentrieren Sie sich darauf, __str__einigermaßen lesbar und __repr__so eindeutig wie möglich zu machen, auch wenn dies das unscharfe unerreichbare Ziel beeinträchtigt, den __repr__zurückgegebenen Wert als Eingabe für akzeptabel zu machen __eval__!

Alex Martelli
quelle
34
Bei meinen Unit-Tests überprüfe ich immer, ob eval(repr(foo))ein Objekt gleich ist foo. Sie haben Recht, dass es außerhalb meiner Testfälle nicht funktioniert, da ich nicht weiß, wie das Modul importiert wird, aber dies stellt zumindest sicher, dass es in einem vorhersehbaren Kontext funktioniert . Ich denke, dies ist eine gute Methode, um zu bewerten, ob das Ergebnis von __repr__explizit genug ist. Wenn Sie dies in einem Komponententest tun, können Sie auch sicherstellen, dass die __repr__folgenden Änderungen an der Klasse vorgenommen werden.
Steven T. Snyder
4
Ich versuche immer sicherzustellen, dass entweder eval(repr(spam)) == spam(zumindest im richtigen Kontext) oder eval(repr(spam))a SyntaxError. Auf diese Weise vermeiden Sie Verwirrung. (Und das gilt fast für die eingebauten und die meisten stdlibs, außer zum Beispiel für rekursive Listen, wo a=[]; a.append(a); print(eval(repr(a)))Sie [[Ellipses]]...) Natürlich mache ich das nicht, um es tatsächlich zu verwenden eval(repr(spam)) , außer als Überprüfung der geistigen Gesundheit in Unit-Tests ... aber ich Kopieren Sie sie manchmal und fügen Sie sie repr(spam)in eine interaktive Sitzung ein.
Abarnert
Warum sollten Container (Listen, Tupel) nicht __str__für jedes Element anstelle von verwendet werden __repr__? Scheint mir einfach falsch zu sein, da ich ein lesbares Element __str__in mein Objekt implementiert habe und wenn es Teil einer Liste ist, sehe ich __repr__stattdessen das hässlichere .
SuperGeo
eval(repr(x))Ich class A(str, Enum): X = 'x'bin gerade auf einen nervigen Fehler gestoßen , der damit zusammenhängt, dass selbst bei eingebauten Typen ein Fehler auftritt: SyntaxError wird aktiviert eval(repr(A.X)). Es ist traurig, aber verständlich. Übrigens eval(str(A.X))funktioniert es tatsächlich, aber natürlich nur, wenn class Aes im Umfang liegt - also ist es wahrscheinlich nicht sehr nützlich.
Max
@SuperGeo Andere Antworten decken dies ab: Container strUse Element reprweil [1, 2, 3]! = ["1", "2, 3"].
mtraceur
163

__repr__: Die Darstellung eines Python-Objekts wird normalerweise von eval wieder in dieses Objekt konvertiert

__str__: ist, was immer Sie denken, ist dieses 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
Andrew Clark
quelle
151

Kurz gesagt, das Ziel von __repr__ist es, eindeutig und __str__lesbar zu sein.

Hier ist ein gutes Beispiel:

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

Lesen Sie diese Dokumentation für Repr:

repr(object)

Gibt eine Zeichenfolge zurück, die eine druckbare Darstellung eines Objekts enthält. Dies ist der gleiche Wert, der durch Conversions (umgekehrte Anführungszeichen) erzielt wird. Es ist manchmal nützlich, als normale Funktion auf diesen Vorgang zugreifen zu können. Bei vielen Typen versucht diese Funktion, eine Zeichenfolge zurückzugeben, die bei Übergabe ein Objekt mit demselben Wert ergibt eval(). Andernfalls ist die Darstellung eine Zeichenfolge in spitzen Klammern, die den Namen des Objekttyps zusammen mit zusätzlichen Informationen enthält oft einschließlich des Namens und der Adresse des Objekts. Eine Klasse kann steuern, was diese Funktion für ihre Instanzen zurückgibt, indem sie eine __repr__()Methode definiert.

Hier ist die Dokumentation für str:

str(object='')

Gibt eine Zeichenfolge zurück, die eine gut druckbare Darstellung eines Objekts enthält. Bei Zeichenfolgen wird die Zeichenfolge selbst zurückgegeben. Der Unterschied repr(object)besteht darin, dass str(object)nicht immer versucht wird, eine Zeichenfolge zurückzugeben, die für akzeptabel ist eval(). Ziel ist es, eine druckbare Zeichenfolge zurückzugeben. Wenn kein Argument angegeben wird, wird die leere Zeichenfolge zurückgegeben ''.

bitoffdev
quelle
1
Was bedeutet druckbare Zeichenfolge hier? Kannst du es bitte erklären?
Vicrobot
115

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__Bietet Sicherungsverhalten, wenn __str__es fehlt.

Man sollte also zuerst eine schreiben __repr__, mit der man ein äquivalentes Objekt aus der zurückgegebenen Zeichenfolge wiederherstellen kann, z. B. mit evaloder durch Eingabe von Zeichen für Zeichen in einer Python-Shell.

Zu einem späteren Zeitpunkt kann man jederzeit eine __str__für den Benutzer lesbare Zeichenfolgendarstellung der Instanz schreiben , wenn man dies für notwendig hält.

__str__

Wenn Sie ein Objekt drucken, oder gibt sie an format, str.formatoder str, dann , wenn eine __str__Methode definiert ist, wird diese Methode aufgerufen werden, andernfalls __repr__wird verwendet.

__repr__

Die __repr__Methode wird von der integrierten Funktion aufgerufen reprund wird in Ihrer Python-Shell wiedergegeben, wenn ein Ausdruck ausgewertet wird, der ein Objekt zurückgibt.

Da es ein Backup für bietet __str__, beginnen Sie mit, wenn Sie nur eines schreiben können__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, wenn Sie für die meisten Objekte eingeben, von was gedruckt wird repr, sollten Sie in der Lage sein, ein gleichwertiges Objekt zu erstellen. Dies ist jedoch nicht die Standardimplementierung.

Standardimplementierung von __repr__

Das Standardobjekt __repr__ist ( C Python-Quelle ) wie folgt :

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, von dem das Objekt stammt, den Klassennamen und die hexadezimale Darstellung seiner Position im Speicher - zum Beispiel:

<__main__.Foo object at 0x7f80665abdd0>

Diese Informationen sind nicht sehr nützlich, aber es gibt keine Möglichkeit abzuleiten, wie man eine kanonische Darstellung einer bestimmten Instanz genau erstellen kann, und sie ist besser als nichts und sagt uns zumindest, wie wir sie im Speicher eindeutig identifizieren können.

Wie kann __repr__nützlich sein?

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

import datetime

Wenn wir datetime.nowdie Shell aufrufen , sehen wir alles, was wir brauchen, um ein äquivalentes datetime-Objekt neu zu erstellen. Dies wird durch die datetime erstellt __repr__:

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

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

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

Es ist ganz einfach, das verlorene Objekt neu zu erstellen, da wir es keiner Variablen zugewiesen haben, indem wir es aus der __repr__Ausgabe kopiert und eingefügt und dann gedruckt haben. 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?

Während der Entwicklung möchten Sie nach Möglichkeit Objekte im gleichen Zustand reproduzieren können. So definiert beispielsweise das datetime-Objekt __repr__( Python-Quelle ). Es ist ziemlich komplex, da alle Attribute erforderlich sind, 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 = "%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

Wenn Ihr Objekt eine besser lesbare Darstellung haben soll, können Sie es als __str__Nächstes implementieren . So implementiert das datetime-Objekt ( Python-Quelle ) __str__, was es leicht macht, da es bereits eine Funktion zum Anzeigen im ISO-Format hat:

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

Set __repr__ = __str__?

Dies ist eine Kritik an einer anderen Antwort, die eine Einstellung vorschlägt __repr__ = __str__.

Die Einstellung __repr__ = __str__ist albern - __repr__ist ein Fallback für __str__und eine __repr__, die für Entwickler beim Debuggen geschrieben wurde, sollte geschrieben werden, bevor Sie eine schreiben __str__.

Sie benötigen eine __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 ein reproduzierbares Beispiel haben, wenn Sie es während der Entwicklung verwenden. Definieren __str__Sie, wann Sie eine von Menschen lesbare Zeichenfolgendarstellung benötigen.

Aaron Hall
quelle
Sollte es nicht etwas in der Art von sein type(obj).__qualname__?
Solomon Ucko
@SolomonUcko Ja, in Python 3 scheint dies der Fall zu sein. Ich habe den Quellcode gesucht, in dem dies implementiert ist, und ich werde meine Antwort mit diesen Informationen aktualisieren, wenn ich sie zusammenstelle.
Aaron Hall
33

Auf Seite 358 des Buches Python Scripting for Computational Science von Hans Petter Langtangen heißt es deutlich

  • Die __repr__Ziele bei einer kompletten String - Darstellung des Objekts;
  • Das __str__ist, eine schöne Zeichenfolge zum Drucken zurückzugeben.

Also verstehe ich sie lieber als

  • repr = reproduzieren
  • str = string (Darstellung)

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

Ein kleines, aber gutes Beispiel finden Sie auf derselben Seite wie folgt:

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'
Yong Yang
quelle
Es ist bei pg. # 351.
Jiten
4
Es ist irreführend, reprals Reproduktion zu bezeichnen. Es ist besser, es als repräsentativ zu betrachten.
NelsonGon
31

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

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

2) __str__()wird aufgerufen, wenn Sie ein Objekt mit einer print-Anweisung verwenden.

3) Im Falle, wenn __str__fehlt, wird dann gedruckt und jede Funktion str()Invokes __repr__()des Objekts.

4) __str__()von Containern führt beim Aufrufen die __repr__()Methode der enthaltenen Elemente aus.

5) str()innerhalb aufgerufen __str__()könnte möglicherweise ohne Basisfall und Fehler bei maximaler Rekursionstiefe wiederkehren.

6) __repr__()kann aufrufen, repr()wodurch versucht wird, eine unendliche Rekursion automatisch zu vermeiden, indem ein bereits dargestelltes Objekt durch ersetzt wird ....

Mangu Singh Rajpurohit
quelle
14

Einfach gesagt:

__str__wird verwendet, um eine Zeichenfolgendarstellung Ihres Objekts anzuzeigen, die von anderen leicht gelesen werden kann .

__repr__wird verwendet , um eine String - Darstellung zeigen das Objekt.

Angenommen, ich möchte eine FractionKlasse erstellen , in der die Zeichenfolgendarstellung eines Bruchs '(1/2)' und das Objekt (Bruchklasse) als 'Bruch (1,2)' dargestellt wird.

So können wir eine einfache Bruchklasse 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)
Zer0
quelle
13

In aller Ehrlichkeit eval(repr(obj))wird nie verwendet. Wenn Sie es verwenden, sollten Sie aufhören, da dies evalgefährlich ist und Zeichenfolgen eine sehr ineffiziente Methode zum Serialisieren Ihrer Objekte darstellen ( picklestattdessen verwenden).

Daher würde ich die Einstellung empfehlen __repr__ = __str__. Der Grund dafür ist , dass str(list)Anrufe reprauf den Elemente (Ich halte dies für eine der größten Design - Fehler von Python zu sein , die nicht von Python 3 angesprochen wurde). Ein tatsächlicher reprwird als Ausgabe von wahrscheinlich nicht sehr hilfreich sein print [your, objects].

Um dies zu qualifizieren, besteht meiner Erfahrung nach der nützlichste Anwendungsfall der reprFunktion darin, eine Zeichenfolge in eine andere Zeichenfolge einzufügen (mithilfe der Zeichenfolgenformatierung). Auf diese Weise müssen Sie sich keine Sorgen mehr machen, dass Sie Anführungszeichen oder Ähnlichem entkommen. Beachten Sie jedoch, dass hier nichts evalpassiert.

asmeurer
quelle
19
Ich denke, das geht am eigentlichen Punkt vorbei. Die Verwendung von eval(repr(obj))ist ein Vernunfttest und eine Faustregel. Wenn das ursprüngliche Objekt korrekt neu erstellt wird, haben Sie eine anständige __repr__Implementierung. Es ist nicht beabsichtigt, dass Sie Objekte tatsächlich auf diese Weise serialisieren.
JWG
7
evalist nicht von Natur aus gefährlich. Ist das nicht gefährlicher als unlink, openoder um Dateien zu schreiben. Sollten wir aufhören, in Dateien zu schreiben, weil ein böswilliger Angriff möglicherweise einen beliebigen Dateipfad verwenden könnte, um Inhalte darin abzulegen? Alles ist gefährlich, wenn es von dummen Leuten dumm benutzt wird. Idiotie ist gefährlich. Mahn-Krüger-Effekte sind gefährlich. evalist nur eine Funktion.
Luis Masuelli
12

Aus einem (inoffiziellen) Python-Referenz-Wiki (Archivkopie) von effbot:

__str__" Berechnet die" informelle "Zeichenfolgendarstellung eines Objekts. Dies unterscheidet sich __repr__darin, dass es kein gültiger Python-Ausdruck sein muss: Stattdessen kann eine bequemere oder präzisere Darstellung verwendet werden. "

Casebash
quelle
3
__repr__ist keinesfalls erforderlich, um einen gültigen Python-Ausdruck zurückzugeben.
Mad Physicist
10

str - Erstellt ein neues String-Objekt aus dem angegebenen Objekt.

repr - Gibt die kanonische Zeichenfolgendarstellung des Objekts zurück.

Die Unterschiede:

str ():

  • macht das Objekt lesbar
  • generiert eine Ausgabe für den Endbenutzer

repr ():

  • benötigt Code, der das Objekt reproduziert
  • generiert eine Ausgabe für den Entwickler
Inconnu
quelle
8

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

  • Ziel von __str__: lesbar
  • Ziel __repr__: eindeutig, möglicherweise maschinenlesbar übereval

Leider ist diese Unterscheidung fehlerhaft, da Python REPL und auch IPython __repr__zum Drucken von Objekten in einer REPL-Konsole verwendet werden (siehe verwandte Fragen zu Python und IPython ). Daher haben Projekte, die auf interaktive Konsolenarbeit ausgerichtet sind (z. B. Numpy oder Pandas), begonnen, die oben genannten Regeln zu ignorieren und __repr__stattdessen eine für Menschen lesbare Implementierung bereitzustellen .

bluenote10
quelle
7

Aus dem Buch Fluent Python :

Eine Grundvoraussetzung für ein Python-Objekt ist die Bereitstellung verwendbarer Zeichenfolgendarstellungen von sich selbst, eine zum Debuggen und Protokollieren, eine andere zur Präsentation für Endbenutzer. Deshalb sind die
speziellen Methoden __repr__und __str__im Datenmodell vorhanden.

Ijaz Ahmad Khan
quelle
5

Hervorragende Antworten decken bereits den Unterschied zwischen __str__und ab __repr__, was für mich darauf hinausläuft, dass erstere auch für Endbenutzer lesbar sind und letztere für Entwickler so nützlich wie möglich sind. Angesichts dessen stelle ich fest, dass die Standardimplementierung von __repr__dieses Ziel häufig nicht erreicht, weil sie weggelassen wird nützliche Informationen für Entwickler.

Wenn ich eine einfache habe __str__, versuche ich aus diesem Grund im Allgemeinen nur, das Beste aus beiden Welten mit so etwas wie:

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

Eine wichtige Sache, die zu beachten ist, ist, dass der Container die __str__enthaltenen Objekte verwendet __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 bevorzugt die Eindeutigkeit gegenüber der Lesbarkeit , den __str__Aufruf eines Aufrufs tupleder enthaltenen Objekte __repr__, die "formale" Darstellung eines Objekts. Obwohl die formale Darstellung schwerer zu lesen ist als eine informelle, ist sie eindeutig und robuster gegen Fehler.

zangw
quelle
Es wird verwendet, __repr__ wenn es ( __str__) nicht definiert ist! Du liegst also falsch.
Jiten
4

In einer Nussschale:

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'
Schattenwanderer
quelle
4
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

Wenn print()aufgerufen wird, wird das Ergebnis decimal.Decimal(23) / decimal.Decimal("1.05")der Rohnummer gedruckt; Diese Ausgabe erfolgt in String-Form, die mit erreicht werden kann __str__(). Wenn wir einfach den Ausdruck eingeben, erhalten wir eine decimal.DecimalAusgabe - diese Ausgabe ist in repräsentativer Form, die mit erreicht werden kann __repr__(). Alle Python-Objekte haben zwei Ausgabeformen. Die Zeichenfolgenform 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 reproduziert.

BattleDrum
quelle
4

__str__kann durch Aufrufen für ein Objekt aufgerufen werden str(obj)und sollte eine von Menschen lesbare Zeichenfolge zurückgeben.

__repr__kann durch Aufrufen für ein Objekt aufgerufen werden repr(obj)und sollte ein internes Objekt (Objektfelder / Attribute) zurückgeben.

Dieses Beispiel kann helfen:

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
Prosti
quelle
3

Verstehe __str__und __repr__unterscheide sie intuitiv und dauerhaft überhaupt.

__str__ Geben Sie den String-getarnten Körper eines bestimmten Objekts zurück, damit er von den Augen gelesen werden kann
__repr__ den realen Fleischkörper eines bestimmten Objekts zurück (geben Sie sich selbst zurück), damit er eindeutig identifiziert werden kann.

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

Bezüglich __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 __repr__Ergebnisse bequem arithmetisch bearbeiten.

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 anwenden __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 schaffen, um weitere Antworten zu finden.

Infinitesimalrechnung
quelle
3
  1. __str__muss ein String-Objekt zurückgeben, während ein __repr__beliebiger Python-Ausdruck zurückgegeben werden kann.
  2. Wenn die __str__Implementierung fehlt, wird die __repr__Funktion als Fallback verwendet. Es gibt keinen Fallback, wenn die __repr__Funktionsimplementierung fehlt.
  3. Wenn die __repr__Funktion eine Zeichenfolgendarstellung des Objekts zurückgibt, können wir die Implementierung der __str__Funktion überspringen .

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

Sampath
quelle
2

__repr__wird überall verwendet, außer durch printund strMethoden (wenn a __str__definiert ist!)

techkuz
quelle