在 Python 的对象模型中,字符串表示协议(String Representation Protocol)定义了对象如何以字符串形式表达自身。

这是 Python 面向对象设计中极具 Pythonic 特征的一环——任何对象都应能用字符串清晰地“自我描述”。

该协议由两个核心特殊方法构成:__str__() 与 __repr__()。

前者用于人类可读的输出,后者用于开发与调试中的精确表示。

<strong>一、什么是字符串表示协议

在 Python 的哲学中,“一切皆对象”,对象不仅要能被操作,也应能被表达。

字符串表示协议正是为此而生,它定义了对象在以下情境下的行为:

当对象被传递给 print() 或 str()。

当对象出现在解释器交互模式下。

当对象被格式化为字符串。

当使用 repr() 函数或调试输出时。

Python 为此设计了两种不同层面的字符串表示:

__str__() → 提供用户友好的、可读性强的描述。

__repr__() → 提供开发者友好的、可再现的表示。

“字符串表示协议”虽未正式被官方命名,但普遍存在于语言机制与实践中,是事实上的协议。

二、字符串表示协议的核心方法

1、__repr__(self)

返回对象的官方字符串表示(official string representation)。

其目标是尽可能精确、明确,并在理想情况下可以被 eval() 重新构造出原对象。

print(repr(p))   # 输出:Point(2, 3)

在标准的 Python 交互模式中,__repr__() 会自动被调用:

Point(2, 3)

2、__str__(self)

返回对象的非正式字符串表示(informal string representation)。

其目标是面向用户、可读性优先,不要求能精确重建对象。

print(p)         # 调用 __str__(),输出:(2, 3)

若类未定义 __str__(),Python 会自动回退到 __repr__() 的结果。

三、两者的区别与调用关系

打开网易新闻 查看精彩图片

也就是说:

__repr__() 是开发者的视角;__str__() 是用户的视角。

示例:同时定义两者

print(repr(v))  # 输出:Vector(1, 2, 3)

四、与格式化和调试的关系

(1)字符串格式化

当对象被用于 f-string、format() 或 % 运算时:

• 默认调用 __format__()(若未定义,则使用 __str__())。

• 格式说明符 !r 强制使用 __repr__()。

• 格式说明符 !s 强制使用 __str__()。

print(f"{i!s}")   # Item(str)

(2)日志与调试输出

调试和日志系统通常偏好使用 repr(),例如 logging 模块或异常堆栈输出中的对象表示。

五、默认行为与自定义策略

如果类没有定义这两个方法,Python 默认继承自 object:

print(repr(Demo())) # <__main__.Demo object at 0x000001>

这类默认表示主要用于调试,包含类名与内存地址。

因此,为自定义类实现友好的 __repr__() 和 __str__() 是良好的编码实践。

常见设计建议如下:

若只能定义一个方法 → 定义 __repr__(),因为它更通用;

保证 __repr__() 可重建对象或至少信息充分;

保证 __str__() 可读性好、语义清晰;

避免 __repr__() 中调用 __str__(),防止递归风险。

小结

字符串表示协议是 Python 对象模型中最直观、最常见的协议之一,它让所有对象都能以字符串形式清晰地表达自身,为调试、日志、交互式编程提供了统一接口。

__repr__() 提供开发者视角的精确表示。

__str__() 提供用户视角的可读表示。

若未定义 __str__(),会自动回退到 __repr__()。

两者在交互模式、print()、日志、格式化等场景中各司其职。

为自定义类实现清晰的字符串表示是 Pythonic 风格的重要体现。

点赞有美意,赞赏是鼓励