print(obj) 输出内存地址是因为未重写__str__和__repr__;__str__面向用户,需简洁可读(如"张三(28岁)"),返回str且不拼接敏感信息;__repr__面向开发者,应尽可能可重建对象(如"person(name='张三', age=28)"),缺失时不会fallback到__str__。

为什么 print(obj) 输出的是 <__main__.person object at></__main__.person>?
因为没重写 __str__ 和 __repr__,Python 默认用内存地址生成字符串。这在调试和日志里完全没法读——你看到的不是“张三,28岁”,而是一串无意义的地址。
__str__ 该返回什么?面向谁?
__str__ 是给人看的,要简洁、可读、带业务语义。它不负责还原对象,也不需要唯一性。
- 返回类型必须是
str,否则会报TypeError: __str__ returned non-string - 别拼接敏感字段(比如密码、token),
__str__可能被日志系统自动采集 - 避免调用耗时操作(如数据库查询、文件读取),print 一下就卡住很常见
- 示例:
def __str__(self):<br> return f"{self.name}({self.age}岁)"
__repr__ 不只是“更详细的 __str__”
__repr__ 面向开发者和调试器,目标是“尽可能还原对象”。理想情况下,eval(repr(obj)) == obj 应成立(虽常因模块路径、不可序列化对象而妥协)。
- 优先包含类名、关键属性,用括号包裹,属性间用逗号分隔(符合 Python 字面量风格)
- 字符串属性值必须加引号,否则
eval会报NameError - 如果对象不可重建(如含
threading.Lock),至少保证输出唯一、可定位,比如加上id(self)或哈希 - 示例:
def __repr__(self):<br> return f"Person(name='{self.name}', age={self.age})"
两个方法都缺时,__repr__ 会自动 fallback 到 __str__ 吗?
不会。只有 __str__ 缺失时,print() 和 str() 才会退回到 __repr__;但 __repr__ 缺失时,repr() 和交互式环境直接显示默认地址,不会尝试用 __str__。
- 这意味着:只写
__str__不够,logging.debug(obj)、pdb 调试、Jupyter 输出仍难读 - 建议始终实现
__repr__,哪怕最简版:f"{self.__class__.__name__}({id(self):x})" - 别让
__repr__返回空字符串或 None,那会导致TypeError
__repr__ 中对属性值的转义处理。比如 name = "Alice's cat",直接插进去会破坏字符串结构,得用 repr(self.name) 而不是 self.name。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











