__str__面向用户,__repr__面向开发者和调试器;前者需返回str类型且避免敏感信息,后者应含类名、关键字段并用!r格式化,禁用耗时操作与未定义属性。

__str__ 和 __repr__ 的核心区别在哪
线上排查时,__str__ 是给用户看的,__repr__ 是给人(尤其是开发者)和调试器看的。别把 __repr__ 写成“美化版字符串”——它得能尽量还原对象,最好能直接 eval() 出原对象(虽不强求,但结构要清晰)。如果两个方法返回一样,等于放弃了一半调试信息。
线上日志里 print(obj) 没反应?检查 __str__ 返回值类型
__str__ 必须返回 str,返回 None、int 或抛异常都会让 print() 报 TypeError: __str__ returned non-string。线上服务一旦触发这个错误,可能静默吞掉整条日志或导致格式错乱。
- 务必用
return str(...)或格式化字符串,别漏return - 避免在
__str__中访问可能为None的属性并直接调用.name—— 加getattr(obj, 'name', 'N/A')或hasattr()防崩 - 敏感字段(如 token、password)别进
__str__,但可在__repr__里用'***'占位
__repr__ 怎么写才对调试友好
理想 __repr__ 应包含类名 + 关键可追溯字段 + 简洁结构。别堆全部属性,重点选能定位实例身份的字段(如 id、pk、url、state)。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
示例:
def __repr__(self):
return f"<order id="{self.id}" status="{self.status}" created_at="{self.created_at!r}">"</order>
- 用
!r格式化字段值(比如str加引号、None显示为None),避免歧义 - 字段顺序按重要性排:身份标识优先(
id),状态次之(status),时间戳靠后 - 避免在
__repr__中触发数据库查询或网络请求——线上调用频繁,容易拖慢日志输出甚至引发死锁
线上环境 __repr__ 被截断?注意日志框架的长度限制
很多日志系统(如 Loguru、structlog)默认截断长字符串,__repr__ 一写太全,关键字段反而被砍掉。不是代码错了,是日志没显示全。
- 控制
__repr__长度:字段值用textwrap.shorten(value, width=20)或手动截取 - 对长列表/字典,只展示长度和前几项:
f"items[{len(self.items)}]={self.items[:3]}" - 本地调试可开全量,但上线前建议加个开关(如
os.getenv('DEBUG_REPR'))做分级输出
最常被忽略的是:__repr__ 里用了未定义的属性或引发 AttributeError,会导致整个对象在日志中显示为 <__main__.myclass object at></__main__.myclass>——看着像正常,实则关键信息全丢了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










