You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现类的__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__方法,于是形成了无限循环:

  1. __repr__遍历到getA,获取到绑定方法
  2. 格式化字符串时需要把绑定方法转成字符串,这会访问它所属的实例self
  3. 访问实例的字符串表示,再次调用__repr__
  4. 重复上述步骤,直到超出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:21:12