实现类的__repr__时访问函数成员触发RecursionError的原因咨询
问题:实现__repr__时触发递归深度超出错误
我尝试给类实现__repr__方法,但当访问类的函数成员并把它的值加入__repr__的返回内容时,出现了“maximum recursion depth exceeded”(递归深度超出最大值)错误。移除类里的所有函数后,__repr__就能正常工作。我打算用跳过函数成员的方式临时处理,但想搞明白递归产生的原因。
简化代码如下:
class C: def __init__(self, a): self.a = a def getA(self): return self.a def __repr__(self): ret_str = self.__class__.__name__ + "\n" for v in dir(self): if v.startswith("__"): continue ret_str += "{} -> {}\n".format(v, getattr(self,v)) return ret_str c = C(1) print(c)
错误信息:
Traceback (most recent call last): File "test.py", line 18, in <module> print(c) File "test.py", line 13, in __repr__ ret_str += "{} -> {}\n".format(v, getattr(self,v)) File "test.py", line 13, in __repr__ ret_str += "{} -> {}\n".format(v, getattr(self,v)) File "test.py", line 13, in __repr__ ret_str += "{} -> {}\n".format(v, getattr(self,v)) [Previous line repeated 163 more times] RecursionError: maximum recursion depth exceeded
递归原因分析
问题出在实例方法的字符串表示会引用所属实例:
当你用getattr(self, 'getA')获取实例上的方法时,得到的是一个「绑定方法(bound method)」——它和当前实例self绑定在一起。当你在格式化字符串中尝试把这个绑定方法转成字符串时,Python会生成它的描述信息,其中必然包含这个方法所属的实例(也就是self)。
而一旦引用到实例self,就会触发实例的__repr__方法,于是形成了无限循环:
__repr__遍历到getA,获取到绑定方法- 格式化字符串时需要把绑定方法转成字符串,这会访问它所属的实例
self - 访问实例的字符串表示,再次调用
__repr__ - 重复上述步骤,直到超出Python的递归深度限制
临时修复方案
你之前想的跳过函数成员是可行的,可以通过判断属性是否为可调用的方法来过滤:
import inspect class C: def __init__(self, a): self.a = a def getA(self): return self.a def __repr__(self): ret_str = self.__class__.__name__ + "\n" for v in dir(self): if v.startswith("__"): continue attr = getattr(self, v) # 跳过方法类型的成员 if inspect.ismethod(attr) or inspect.isfunction(attr): continue ret_str += "{} -> {}\n".format(v, attr) return ret_str c = C(1) print(c)
或者用更简单的callable()判断:
if callable(attr): continue
内容的提问来源于stack exchange,提问作者Marcel Preda
相关产品推荐
相关产品推荐

