__str__是面向用户的简洁可读表示,__repr__是面向开发者的无歧义可复现表示;二者必须返回str,__repr__应尽量满足eval(repr(obj))语义等价,且缺失__str__时会自动回退到__repr__。

直接说结论: __str__ 是给人看的字符串表示,__repr__ 是给开发者/调试器看的“可复现”表示;二者都该返回 str,且 __repr__ 应尽量满足 eval(repr(obj)) == obj(至少语义上成立)。
什么时候该重写 __str__?
当你希望 print(obj) 或 str(obj) 输出易读、带业务含义的文本时。比如日志里打印订单对象,你不想看到 <order object at></order>,而想要 "Order #12345, status: paid"。
- 只影响
print()、str()、f-string 中的{obj}等“用户友好”场景 - 不必严格可执行,允许省略细节(如不显示内部 ID 或时间戳)
- 避免换行、控制字符;保持单行、UTF-8 可读
- 如果没定义
__str__,Python 会 fallback 到__repr__
为什么 __repr__ 更关键?
它被 repr()、交互式解释器回显、logging 默认格式、pytest 断言失败输出等大量底层机制调用。写得不好,调试时就只能靠 obj.__dict__ 硬翻。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 目标是“无歧义 + 尽量可重建”,例如
Point(x=1.0, y=2.0)比"(1.0, 2.0)"更好 - 参数名要显式写出,避免位置歧义:
datetime(2023, 10, 5)比"2023-10-05"更明确 - 若对象不可重建(如含文件句柄、网络连接),至少保留类型+关键状态:
"<connection state="OPEN" timeout="30s">"</connection> - 别返回空字符串或
None—— 这会导致TypeError: __repr__ returned non-string
__str__ 和 __repr__ 写反了会怎样?
常见错误是把 __repr__ 当成美化输出来写,结果在 logging.debug("obj=%r", obj) 里打出一堆带颜色 ANSI 码,或者在 pytest 报错中看到冗长 HTML 片段 —— 这些本该由 __str__ 负责,但 __repr__ 被污染后就全乱了。
-
__repr__返回非字符串(如return f"[{self.name}]"但忘了加str()包裹)→ 直接抛TypeError -
__str__返回None→ 打印出"None",而不是预期内容 - 两个方法都未实现 → 统一 fallback 到默认的
<classname object at></classname> - 用
f"{obj!r}"强制触发__repr__时,若它太重(比如触发数据库查询),会导致性能意外下降
真正难的不是语法,而是判断哪些字段该进 __repr__(比如缓存字段、临时状态通常不该出现),以及如何平衡可读性与可重建性。很多团队最后发现:写个专用的 to_dict() 或 debug_info() 方法,比硬塞进 __repr__ 更可控。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










