| 术语 | 英文缩写/同义词 | 谁 | 与 Python print 的关系 |
|---|---|---|---|
| 最终用户 | end-user, lay-user, consumer | 完全不懂代码,用图形界面、手机 App | 根本看不到 print 输出;需要 UI/图表/自然语言 |
| 开发者用户 | developer-user, programmer-user | 写脚本、跑 Jupyter、看日志 | print([1,2,34]) 的默认受众;认识 [] 字面量 |
| 运维/运维开发 | DevOps, SRE | 在终端里看日志、调试线上服务 | 同上,常配合 logging |
| 库作者 | library author | 给别人写包 | 决定自己类的 __str__/__repr__ 策略 |
| 调试器/REPL | debugger, evaluator | 机器角色,但“看”的是 __repr__ |
需要可复现、可 eval 的字符串 |
__str__ 的“human-readable”就不会绕晕了,这些人不是编程小白,他们认识 []、{}、'' 这些基本语法糖。[1, 2, 34] 再进化成“一行一个数字”或“柱状图”是应用层的责任,而不是标准库 list 的 __str__ 的责任。Python __str__ 给人瞄一眼;__repr__ 给开发者复现对象
三、怎样快速判断该写哪个?
__str__(或语言对应接口),要短、可读。__repr__(或 %#v/util.inspect/调试属性),给开发者救命。__repr__——调试时不会后悔;Python 回退机制:print(obj) 发现没有 __str__ 会自动用 __repr__。| 协议 | 触发场景 | 设计目标 | 典型实现 |
|---|---|---|---|
__str__ |
print(obj)、str(obj)、'{0}'.format(obj) |
让人类终端用户看懂——友好、简洁、可省略细节 | datetime.datetime(2025,11,19,14,30) → 2025-11-19 14:30 |
__repr__ |
交互式解释器回车、repr(obj)、调试器/watch 窗口 |
让开发者/机器拿到足够信息——理想情况 |
交互式解释器回车,会看到实际类型,而在交互式解释器里面输入print(a)是去掉引号的:
repr(a),一定给你能看到类型/能否 eval 的字符串,所以字符串会带着引号 'hello'。print(a) → 走的是 str(a),把引号去掉,因为引号对人眼来说属于“语法噪音”显式 print(a) → 走的是 str(a),把引号去掉,因为引号对人眼来说属于“语法噪音”。为什么我觉得显示引号比较好,不觉得是噪音?
print() 的输出最常被直接拿去给人读、写进日志、贴进报告,而引号在这类场景里确实会:repr() 的“冗余”就成了优点。为什么交互式终端会调用repr,准备用到哪个场景?
快速查看对象内部状态
>>> class MyClass: ... def __init__(self, x): ... self.x = x ... def __repr__(self): ... return f"MyClass(x={self.x})" ... def __str__(self): ... return f"MyClass with x={self.x}" ... >>> obj = MyClass(42) >>> obj # 交互式终端自动调用 repr() MyClass(x=42) # 直接显示类型和属性值,方便调试
str() 和 repr() 的核心区别确实体现在使用场景和目标受众的意图上,尽管两者最终都是给人(开发者)看的,但目的不同:
✅ str(obj):面向“终端用户”或“日志输出”的可读性
- 目标:生成对人类友好的、简洁明了的字符串表示。
- 典型用途:
- 用户界面显示(如 Web 页面、命令行工具输出)
- 日志记录中的信息展示
- 异常消息中的对象描述
- 特点:
- 忽略技术细节(如引号、转义符)
- 更注重语义清晰而非结构完整
✅ repr(obj):面向“开发者”的调试与重现能力
- 目标:提供无歧义的对象表示,理想情况下能通过
eval(repr(obj)) 重建对象(虽然不是强制要求,但这是设计哲学)。
- 典型用途:
- 调试器中查看变量状态
- REPL(交互式解释器)中自动调用
- 单元测试中的断言输出
- 特点:
- 包含类型信息、引号、转义字符等
- 尽可能“精确”、“唯一”、“可逆”