PyCharm控制台运行自定义__repr__方法时异常重复打印的原因
问题背景
以下Python代码定义了类B:__init__方法会打印提示并初始化空列表属性a,自定义的__repr__方法会打印a的长度,拼接a内元素为字符串后返回:
class B: def __init__(self): print('boo!') self.a = [] def __repr__(self): print(len(self.a)) ret = '' for a in self.a: ret += str(a) return ret
使用搭载Python 3.8.6、IPython 7.31.0内核的PyCharm控制台运行代码时,出现了异常重复打印现象,运行输出如下:
>>> b = B() boo! 0 0 >> b Out[4]: 0 0 0 0 0 0 0 0 0 0 0 >> 2 + 3 Out[5]: 5 0 0 0 0 0 0 0 0 0 0
该异常现象在命令行运行的原生Python REPL、独立IPython环境中均无法复现。
异常产生原因
- 核心诱因是代码写法违反Python设计规范:
__repr__方法的唯一职责是返回对象的字符串表示,严禁在方法内部实现打印、修改对象属性等带副作用的逻辑。示例代码在__repr__中直接调用print(len(self.a)),本身就是错误用法。 - 重复打印的触发方是PyCharm控制台的内置辅助逻辑:和原生REPL、独立IPython仅在用户要求直接输出对象值时才调用
__repr__不同,PyCharm控制台为了实现变量监控面板实时刷新、代码补全对象提示、执行结果预览等IDE功能,会在后台频繁隐式调用当前命名空间内所有对象的__repr__,用于获取对象的展示信息。 - 每次后台隐式调用
__repr__都会触发方法内写死的打印逻辑,因此会不断输出0。哪怕执行2+3这类和B类实例完全无关的代码,PyCharm在执行完成后也会全量扫描当前命名空间的所有变量、刷新监控状态,扫描过程中调用到实例b的__repr__,就会继续输出重复的0。
修正方案:移除
__repr__方法内的打印语句,将需要展示的长度信息直接拼接到返回值中即可,参考写法:def __repr__(self): ret = f"a的长度:{len(self.a)},内容:" for item in self.a: ret += str(item) return ret
内容的提问来源于stack exchange,提问作者AveryL
相关产品推荐
相关产品推荐

