Python __repr__ 方法
最后修改于 2025 年 4 月 8 日
本综合指南探讨了 Python 的 __repr__ 方法,该方法是返回对象的官方字符串表示的特殊方法。
基本定义
__repr__ 方法返回对象的字符串表示。它由 repr() 内置函数调用,并且应该是明确的。
一个好的 __repr__ 应该看起来像一个有效的 Python 表达式,可以重新创建该对象。 它主要用于调试和开发。
基本的 __repr__ 实现
这是一个简单的实现,展示了 __repr__ 如何与基本类一起工作。 该方法应返回一个字符串。
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(3, 4)
print(repr(p)) # Output: Point(3, 4)
此示例展示了正确的 __repr__ 实现。 输出看起来像一个有效的 Python 表达式,可以重新创建该对象。
当您直接打印对象或使用 repr() 时,Python 会调用此方法来获取字符串表示。
__repr__ vs __str__
__repr__ 和 __str__ 的用途不同。 __repr__ 供开发人员使用,而 __str__ 供最终用户使用。
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __repr__(self):
return f"Book('{self.title}', '{self.author}')"
def __str__(self):
return f"{self.title} by {self.author}"
book = Book("Python Crash Course", "Eric Matthes")
print(repr(book)) # Book('Python Crash Course', 'Eric Matthes')
print(str(book)) # Python Crash Course by Eric Matthes
此示例演示了差异。 __repr__ 显示如何重新创建对象,而 __str__ 提供用户友好的字符串。
如果未定义 __str__,Python 将使用 __repr__ 作为后备。
__repr__ 用于调试
一个好的 __repr__ 对于调试非常宝贵,因为它显示了对象的精确状态。 这是一个具有更复杂类的示例。
class ShoppingCart:
def __init__(self):
self.items = []
def add_item(self, product, quantity):
self.items.append((product, quantity))
def __repr__(self):
items_repr = ', '.join(
f"('{p}', {q})" for p, q in self.items
)
return f"ShoppingCart([{items_repr}])"
cart = ShoppingCart()
cart.add_item("Apple", 3)
cart.add_item("Banana", 5)
print(repr(cart))
# Output: ShoppingCart([('Apple', 3), ('Banana', 5)])
此 __repr__ 显示购物车的完整状态,包括所有商品及其数量。 它非常适合调试。
该表示形式包括嵌套结构,并保持可以用于重新创建对象的精确格式。
__repr__ 与继承
使用继承时,应在 __repr__ 中包含类名和所有相关属性。 这是正确的方法。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"{self.__class__.__name__}({self.name!r}, {self.age})"
class Employee(Person):
def __init__(self, name, age, employee_id):
super().__init__(name, age)
self.employee_id = employee_id
def __repr__(self):
return (f"{self.__class__.__name__}({self.name!r}, "
f"{self.age}, {self.employee_id!r})")
emp = Employee("John Doe", 30, "E12345")
print(repr(emp)) # Employee('John Doe', 30, 'E12345')
此示例展示了通过继承实现的正确的 __repr__。 子类包含父类和子类的所有属性。
使用 self.__class__.__name__ 使表示即使在子类化的情况下也能正确工作。
__repr__ 用于自定义容器
对于类似容器的类,__repr__ 应该模仿 Python 的内置容器。 这是一个使用自定义列表类的示例。
class TaggedList:
def __init__(self, tag, *items):
self.tag = tag
self.items = list(items)
def __repr__(self):
items_repr = ', '.join(repr(item) for item in self.items)
return f"{self.__class__.__name__}({self.tag!r}, {items_repr})"
def __str__(self):
return f"{self.tag}: {', '.join(str(item) for item in self.items)}"
tags = TaggedList("Numbers", 1, 2, 3, 4)
print(repr(tags)) # TaggedList('Numbers', 1, 2, 3, 4)
此 __repr__ 遵循 Python 的容器类型约定,显示类名和逗号分隔列表中包含的所有元素。
该表示形式可用于完全按照原来的方式重新创建对象,这是 __repr__ 的主要目标。
最佳实践
- 务必明确: 表示形式应清楚地标识对象
- 使其可执行: 理想情况下,eval(repr(obj)) 应该重新创建该对象
- 包含所有状态: 不要省略重要的属性
- 使用类名: 帮助识别对象类型
- 保持可读性: 平衡完整性和可读性
资料来源
作者
列出所有 Python 教程。