Implementierung der __repr__-Methode
Zusätzlich zu __str__ bietet Python eine weitere spezielle Methode für die Zeichenkettenrepräsentation: __repr__. Während __str__ dazu dient, eine für Menschen lesbare Darstellung bereitzustellen, soll __repr__ eine eindeutige Darstellung eines Objekts liefern, die verwendet werden kann, um das Objekt, wenn möglich, neu zu erstellen.
Verständnis der __repr__-Methode
Die __repr__-Methode wird aufgerufen, wenn Sie die Funktion repr() für ein Objekt verwenden oder wenn Sie ein Objekt in einer interaktiven Sitzung anzeigen. Sie sollte eine Zeichenkette zurückgeben, die, wenn sie an eval() übergeben wird, ein äquivalentes Objekt erstellen würde (wenn möglich).
Aktualisieren wir unsere Book-Klasse, um eine __repr__-Methode einzuschließen:
-
Öffnen Sie book.py im Editor.
-
Aktualisieren Sie den Code, um eine __repr__-Methode einzuschließen:
class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
def __str__(self):
return f'"{self.title}" by {self.author} ({self.pages} pages)'
def __repr__(self):
return f'Book("{self.title}", "{self.author}", {self.pages})'
## Create book objects
book1 = Book("The Great Gatsby", "F. Scott Fitzgerald", 180)
book2 = Book("To Kill a Mockingbird", "Harper Lee", 281)
## Print the books (uses __str__)
print("String representation (using __str__):")
print(book1)
print(book2)
## Get the representation (uses __repr__)
print("\nRepresentation (using __repr__):")
print(repr(book1))
print(repr(book2))
-
Speichern Sie die Datei.
-
Führen Sie das Skript aus:
python3 book.py
Sie sollten eine Ausgabe wie diese sehen:
String representation (using __str__):
"The Great Gatsby" by F. Scott Fitzgerald (180 pages)
"To Kill a Mockingbird" by Harper Lee (281 pages)
Representation (using __repr__):
Book("The Great Gatsby", "F. Scott Fitzgerald", 180)
Book("To Kill a Mockingbird", "Harper Lee", 281)
Unterschiede zwischen __str__ und __repr__
Die Hauptunterschiede zwischen __str__ und __repr__ sind:
__str__ ist für eine für Menschen lesbare Ausgabe gedacht, während __repr__ für Entwickler und Debugging gedacht ist.
- Wenn
__str__ nicht definiert ist, aber __repr__ definiert ist, verwendet Python __repr__ als Fallback für str() oder print().
__repr__ sollte idealerweise eine Zeichenkette zurückgeben, die das Objekt neu erstellen kann, wenn es an eval() übergeben wird, obwohl dies nicht immer möglich oder notwendig ist.
Die eval()-Funktion mit __repr__
Wenn sie korrekt implementiert ist, kann die von __repr__ zurückgegebene Zeichenkette mit eval() verwendet werden, um das Objekt neu zu erstellen. Sehen wir uns das in Aktion an:
-
Erstellen Sie eine neue Datei namens repr_eval.py:
-
Fügen Sie den folgenden Code hinzu:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Point at ({self.x}, {self.y})"
def __repr__(self):
return f"Point({self.x}, {self.y})"
## Create a point
p1 = Point(3, 4)
## Get the repr string
repr_str = repr(p1)
print(f"Representation: {repr_str}")
## Use eval to recreate the object
p2 = eval(repr_str)
print(f"Recreated object: {p2}")
## Verify they have the same values
print(f"p1.x = {p1.x}, p1.y = {p1.y}")
print(f"p2.x = {p2.x}, p2.y = {p2.y}")
-
Speichern Sie die Datei.
-
Führen Sie das Skript aus:
python3 repr_eval.py
Sie sollten eine Ausgabe wie diese sehen:
Representation: Point(3, 4)
Recreated object: Point at (3, 4)
p1.x = 3, p1.y = 4
p2.x = 3, p2.y = 4
Dies zeigt, dass wir das ursprüngliche Objekt mithilfe der von __repr__ zurückgegebenen Zeichenkette und der Funktion eval() neu erstellen können.
Wann welche Methode verwendet werden soll
- Verwenden Sie
__init__, um den Anfangszustand Ihrer Objekte einzurichten.
- Verwenden Sie
__str__, um eine für Menschen lesbare Darstellung für Endbenutzer bereitzustellen.
- Verwenden Sie
__repr__, um eine präzise, eindeutige Darstellung für Entwickler und Debugging bereitzustellen.
Praktische Übung: Ein vollständiges Beispiel
Lassen Sie uns alles zusammenfügen, indem wir eine Rectangle-Klasse mit allen drei speziellen Methoden erstellen:
-
Erstellen Sie eine neue Datei namens rectangle.py:
-
Fügen Sie den folgenden Code hinzu:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
def __str__(self):
return f"Rectangle with width {self.width} and height {self.height}"
def __repr__(self):
return f"Rectangle({self.width}, {self.height})"
## Create rectangles
rect1 = Rectangle(5, 10)
rect2 = Rectangle(3, 7)
## Display information about the rectangles
print(f"Rectangle 1: {rect1}")
print(f"Area: {rect1.area()}")
print(f"Perimeter: {rect1.perimeter()}")
print(f"Representation: {repr(rect1)}")
print("\nRectangle 2: {0}".format(rect2))
print(f"Area: {rect2.area()}")
print(f"Perimeter: {rect2.perimeter()}")
print(f"Representation: {repr(rect2)}")
## Recreate a rectangle using eval
rect3 = eval(repr(rect1))
print(f"\nRecreated rectangle: {rect3}")
print(f"Is it the same area? {rect3.area() == rect1.area()}")
-
Speichern Sie die Datei.
-
Führen Sie das Skript aus:
python3 rectangle.py
Sie sollten eine Ausgabe wie diese sehen:
Rectangle 1: Rectangle with width 5 and height 10
Area: 50
Perimeter: 30
Representation: Rectangle(5, 10)
Rectangle 2: Rectangle with width 3 and height 7
Area: 21
Perimeter: 20
Representation: Rectangle(3, 7)
Recreated rectangle: Rectangle with width 5 and height 10
Is it the same area? True
Dieses Beispiel zeigt, wie alle drei speziellen Methoden (__init__, __str__ und __repr__) zusammenarbeiten, um eine gut gestaltete Klasse zu erstellen.