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 教程。