使用 __repr__ 方法的意外递归循环

Unintended recursive loop with __repr__ method

我想显示一个实例的所有可访问属性的列表,所以我试试这个

class Test:
    a=2     #initializing some attribute
    b=1     #initializing some attribute
    def some_method(self):
        attr=[]                 
        for k in [i for i in dir(self) if not i.startswith('__')]:
            attr.append(f'{k}={getattr(self,k)}')      #to collect all attributes and their values pair
        return attr
    def __repr__(self):                                #because i want to overload print behavior
        return str(self.some_method())
some_instance=Test()
print(some_instance) 

它返回了一个错误:

RecursionError: maximum recursion depth exceeded while calling a Python object

为什么会这样?以及如何解决这个问题?

正如评论中指出的那样,repr(Test().some_method) 调用了它所在对象的 repr,产生了一个永无止境的父子 repr 方法调用堆栈。 如果您对显示可调用成员不感兴趣,您可以将它们过滤掉,这样它们就不会被要求成为字符串的一部分:

class Test:
    a=2     #initializing some attribute
    b=1     #initializing some attribute
    def some_method(self):
        attr=[]                 
        for k in dir(self):
            val = getattr(self, k)
            if not k.startswith('__') and not callable(val):
                attr.append(f'{k}={val}')      #to collect all attributes and their values pair
        return attr
    def __repr__(self):                                #because i want to overload print behavior
        return str(self.some_method())
some_instance=Test()

然后print(some_instance)显示

['a=2', 'b=1']

您可以使用 __str__ 而不是 __repr__ 来重载打印。 如果您必须使用 __repr__,则使用 isinstance() 将属性值的类型与标准库中的 types.MethodType 进行比较。