__str__面向用户,应返回易读简洁的字符串;__repr__面向开发者,需可复现、含类型信息、适合调试,优先实现且避免重操作。

__str__ 是给用户看的,__repr__ 是给开发者看的
直接说结论:__str__ 应该返回一个**易读、简洁、面向终端用户**的字符串,比如 "User(name='Alice', age=30)";而 __repr__ 必须尽可能返回一个**可复现、带类型信息、适合调试**的字符串,理想情况下能直接用 eval() 重建对象(虽不强制,但这是设计意图)。如果只实现一个,优先写 __repr__ —— 因为 print() 和日志里没定义 __str__ 时会自动 fallback 到 __repr__,但反过来不行。
常见错误:把 __repr__ 写成缩略版 __str__
很多人误以为 __repr__ 就是“更短的字符串”,于是写成 return f"User({self.name})"。这会导致两个问题:
- 丢失关键字段(比如
age、id),调试时看不出对象真实状态 - 没标注类名,日志里一堆
"Alice"根本分不清是User还是Profile - 字段值含空格或引号时,不加引号或转义会破坏可读性甚至语法合法性
正确做法是显式包含类名和所有关键属性,并对字符串字段加引号:return f"User(name={self.name!r}, age={self.age})"。注意 !r 会自动调用 repr(),处理好引号和转义。
交互式环境里 print() 和直接敲变量名的区别
在 IPython 或 Python REPL 中:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 输入
user = User("Bob", 25)后直接敲user→ 触发__repr__ - 输入
print(user)或logging.info(user)→ 触发__str__(如果定义了);否则 fallback 到__repr__ -
str(user)调__str__,repr(user)强制调__repr__
这意味着你在写 CLI 工具时,__str__ 控制 print() 输出;但在写库时,别依赖用户一定看到 __str__ —— 很多人调试只敲变量名,所以 __repr__ 的质量直接影响第一印象。
性能与兼容性提醒:避免在 __repr__ 中做重操作
__repr__ 可能在日志、异常 traceback、pdb 调试中被频繁调用,甚至在对象还没完全初始化好时就被触发(比如 __init__ 抛异常前)。所以:
- 不要在
__repr__里访问数据库、读文件、调远程 API - 避免调用可能抛异常的属性(如未初始化的
self._cache),可用getattr(self, '_cache', 'N/A')防御 - 如果对象字段很多,考虑只展示关键字段,或加长度限制(如
self.description[:50] + '...') - 在
__str__里可以更自由地格式化,但也要避免隐式 IO —— 毕竟print()可能出现在热路径上
最常被忽略的一点:当子类继承父类且只重写 __str__ 时,__repr__ 仍沿用父类的——这容易导致父类 __repr__ 打印出子类对象却显示父类名,造成混淆。务必检查继承链上的 __repr__ 是否准确反映当前类。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










