Python-Objekt .__ repr __ (self) sollte ein Ausdruck sein?

73

Ich habe mir die eingebauten Objektmethoden in der Python-Dokumentation angesehen und war an der Dokumentation für interessiert object.__repr__(self). Hier ist, was es sagt:

Wird von der integrierten Funktion repr () und von Zeichenfolgenkonvertierungen (umgekehrte Anführungszeichen) aufgerufen, um die „offizielle“ Zeichenfolgendarstellung eines Objekts zu berechnen. Wenn möglich, sollte dies wie ein gültiger Python-Ausdruck aussehen, mit dem ein Objekt mit demselben Wert (in einer geeigneten Umgebung) neu erstellt werden kann. Wenn dies nicht möglich ist, sollte eine Zeichenfolge der Form <... eine nützliche Beschreibung ...> zurückgegeben werden. Der Rückgabewert muss ein Zeichenfolgenobjekt sein. Wenn eine Klasse repr (), aber nicht str () definiert, wird repr () auch verwendet, wenn eine "informelle" Zeichenfolgendarstellung von Instanzen dieser Klasse erforderlich ist.

Dies wird normalerweise zum Debuggen verwendet. Daher ist es wichtig, dass die Darstellung reich an Informationen und eindeutig ist

Das Interessanteste für mich war ...

Wenn möglich, sollte dies wie ein gültiger Python-Ausdruck aussehen, mit dem ein Objekt mit demselben Wert neu erstellt werden kann

... aber ich bin mir nicht sicher, was das genau bedeutet. Es heißt, es sollte wie ein Ausdruck aussehen , mit dem das Objekt neu erstellt werden kann. Bedeutet dies jedoch, dass es nur ein Beispiel für die Art von Ausdruck sein sollte, die Sie verwenden könnten, oder ob es sich um einen tatsächlichen Ausdruck handelt, der ausgeführt werden kann (eval) etc ..) um das Objekt neu zu erstellen? Oder ... sollte es nur eine Wiederholung des tatsächlichen Ausdrucks sein, der zu reinen Informationszwecken verwendet wurde?

Im Allgemeinen bin ich etwas verwirrt darüber, was ich genau hier einfügen soll.

Alex McBride
quelle
23
Diese Frage ist mit den offiziellen Kursnotizen zu MITs Online 6.00.1x: Einführung in die Informatik verknüpft .
Dotancohen

Antworten:

69
>>> from datetime import date
>>>
>>> repr(date.today())        # calls date.today().__repr__()
'datetime.date(2009, 1, 16)'
>>> eval(_)                   # _ is the output of the last command
datetime.date(2009, 1, 16)

Die Ausgabe ist eine Zeichenfolge, die vom Python-Interpreter analysiert werden kann und zu einem gleichen Objekt führt.

Wenn dies nicht möglich ist, sollte eine Zeichenfolge in Form von zurückgegeben werden <...some useful description...>.

Georg Schölly
quelle
6
Beachten Sie den Nachteil des Versuchs, dass Ihr __repr __ () einen Ausdruck erzeugt, der eine Kopie des Objekts zurückgibt: Sie müssen davon ausgehen, dass das Originalpaket vollständig importiert wurde. Wenn Sie nur die drei Zeilen von Georg ausführen, erhalten Sie "NameError: Name 'datetime' ist nicht definiert", da das datetime-Paket nie importiert wurde. Es wurde nur "Datum" von "Datum / Uhrzeit" importiert.
Michael Scott Cuthbert
32

Es sollte ein Python-Ausdruck sein, der bei Auswertung ein Objekt mit genau den gleichen Eigenschaften wie dieses erstellt. Wenn Sie beispielsweise eine FractionKlasse haben, die zwei Ganzzahlen enthält, einen Zähler und einen Nenner, __repr__()sieht Ihre Methode folgendermaßen aus:

# in the definition of Fraction class
def __repr__(self):
    return "Fraction(%d, %d)" % (self.numerator, self.denominator)

Angenommen, der Konstruktor nimmt diese beiden Werte an.

Jeremy Ruten
quelle
13

Richtlinie: Wenn Sie eine genaue Darstellung prägnant bereitstellen können , formatieren Sie sie als Python-Ausdruck (was bedeutet, dass sie im richtigen Kontext sowohl ausgewertet als auch direkt in den Quellcode kopiert werden kann). Wenn Sie eine ungenaue Darstellung bereitstellen , verwenden Sie das <...>Format .

Es gibt viele mögliche Darstellungen für jeden Wert, aber die für Python-Programmierer interessanteste ist ein Ausdruck, der den Wert neu erstellt. Denken Sie daran, dass diejenigen, die Python verstehen, die Zielgruppe sind - und deshalb sollten ungenaue Darstellungen auch den relevanten Kontext enthalten. Selbst die Standardeinstellung <XXX object at 0xNNN>ist zwar fast völlig nutzlos, bietet jedoch den Typ id()(zur Unterscheidung verschiedener Objekte) und den Hinweis, dass keine bessere Darstellung verfügbar ist.


quelle
4

"aber bedeutet das, dass es nur ein Beispiel für die Art von Ausdruck sein sollte, die Sie verwenden könnten, oder sollte es ein tatsächlicher Ausdruck sein, der ausgeführt werden kann (eval etc ..), um das Objekt neu zu erstellen? Oder ... sollte es sein nur eine Wiederholung des tatsächlichen Ausdrucks, der zu reinen Informationszwecken verwendet wurde? "

Wow, das ist viel Handdrücken.

  1. Ein "Beispiel für die Art von Ausdruck, die Sie verwenden könnten" wäre keine Darstellung eines bestimmten Objekts. Das kann nicht nützlich oder sinnvoll sein.

  2. Was ist der Unterschied zwischen "einem tatsächlichen Ausdruck, der ... das Objekt neu erstellen kann" und "einer Neuausrichtung des tatsächlichen Ausdrucks, der [zum Erstellen des Objekts] verwendet wurde"? Beides ist ein Ausdruck, der das Objekt erstellt. Es gibt keinen praktischen Unterschied zwischen diesen. Ein Repr-Aufruf kann entweder einen neuen Ausdruck oder den ursprünglichen Ausdruck erzeugen. In vielen Fällen sind sie gleich.

Beachten Sie, dass dies nicht immer möglich, praktisch oder wünschenswert ist.

In einigen Fällen werden Sie feststellen, dass repr () eine Zeichenfolge darstellt, die eindeutig kein Ausdruck jeglicher Art ist. Die Standardeinstellung repr () für eine von Ihnen definierte Klasse ist als Ausdruck nicht hilfreich.

In einigen Fällen haben Sie möglicherweise gegenseitige (oder zirkuläre) Verweise zwischen Objekten. Der Repr () dieser verworrenen Hierarchie kann keinen Sinn ergeben.

In vielen Fällen wird ein Objekt schrittweise über einen Parser erstellt. Zum Beispiel aus XML oder JSON oder so. Was wäre der Repräsentant? Das ursprüngliche XML oder JSON? Ganz klar nicht, da sie nicht Python sind. Es könnte ein Python-Ausdruck sein, der das XML generiert hat. Für ein gigantisches XML-Dokument ist es jedoch möglicherweise nicht möglich, einen einzelnen Python-Ausdruck zu schreiben, der das funktionale Äquivalent zum Parsen von XML darstellt.

S.Lott
quelle
Das ist der Grund: Wenn dies nicht möglich ist (um einen gültigen Python-Ausdruck zu erstellen), sollte eine Zeichenfolge der Form <... eine nützliche Beschreibung ...> zurückgegeben werden. Wenn Sie keine Zeichenfolge angeben können, die direkt in Code übersetzt werden kann, geben Sie einfach eine nützliche Beschreibung in '<...>' ein.
Wallace Howery
4

"Repr" bedeutet Repräsentation. Zuerst erstellen wir eine Instanz der Klassenkoordinate.

x = Coordinate(3, 4) 

Wenn wir dann x in die Konsole eingeben, ist die Ausgabe

<__main__.Coordinate at 0x7fcd40ab27b8>

Wenn Sie repr () verwenden:

>>> repr(x)
Coordinate(3, 4)

Die Ausgabe entspricht der von 'Koordinate (3, 4)', außer dass es sich um eine Zeichenfolge handelt. Sie können damit eine Koordinateninstanz neu erstellen.

Abschließend druckt repr () meathod eine Zeichenfolge aus, die die Darstellung des Objekts darstellt.

zhenXiongChen
quelle
2

Um zu sehen, wie die Repr innerhalb einer Klasse funktioniert, führen Sie den folgenden Code zuerst mit und dann ohne die Repr- Methode aus.

class Coordinate (object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def getX(self):
        # Getter method for a Coordinate object's x coordinate.
        # Getter methods are better practice than just accessing an attribute directly
        return self.x
    def getY(self):

        # Getter method for a Coordinate object's y coordinate
        return self.y

    def __repr__(self):  #remove this and the next line and re-run
        return 'Coordinate(' + str(self.getX()) + ',' + str(self.getY()) + ')' 

>>>c = Coordinate(2,-8)
>>>print(c)
Saeed Ahmed
quelle
1
Ich habe die __repr__Funktion durch Tauschen return 'Coordinate(' + str(self.getX()) + ',' + str(self.getY()) + ')'mitreturn 'Coordinate({},{})'.format(self.getX(), self.getX())
Helcode
0

Ich denke, die Verwirrung hier wurzelt im Englischen. Ich meine __repr__(); Abkürzung für 'Darstellung' des Wertes, den ich vermute, wie @ S.Lott sagte

"Was ist der Unterschied zwischen" einem tatsächlichen Ausdruck, der ... das Objekt neu erstellen kann "und" einer Neuausrichtung des tatsächlichen Ausdrucks, der [zum Erstellen des Objekts] verwendet wurde "? Beide sind ein Ausdruck, der das Objekt erstellt. Es gibt keinen praktische Unterscheidung zwischen diesen. Ein Repr-Aufruf könnte entweder einen neuen Ausdruck oder den ursprünglichen Ausdruck erzeugen. In vielen Fällen sind sie gleich. "

In einigen Fällen können sie jedoch unterschiedlich sein. Z.B; Koordinatenpunkte möchten Sie vielleicht c.coordinatezurückgeben: 3,5aber c.__repr__um zurückzukehren Coordinate(3, 5). Hoffe das macht mehr Sinn ...

sle7en
quelle