__repr__中的函数导致无限递归

时间:2018-01-30 05:01:05

标签: python recursion repr

我正在学习Python,我尝试编写以下代码。

class AttributeDisplay:
    '''Display all attributes of a class in __repr__.
    It can be inherited.'''
    def gatherAttributes(self):
        '''Gather all attributes and concatenate them
        as a string'''
        def getAttributeNameAndValue(key):
            return '[%s] - [%s]' % (key, getattr(self, key))
        return '\n'.join((map(getAttributeNameAndValue, sorted(self.__dict__))))

    def __repr__(self):
        '''Print all attributes'''
        attr = self.gatherAttributes() # omitting () results in infinite recursion
        return '[Class: %s]\n%s' % (self.__class__.__name__, attr)

我不小心省略了括号,而attr变成了函数而不是字符串。但是,当我调用print(X)时,它会进入无限递归。

错误的代码如下。

def __repr__(self):
    '''Print all attributes'''
    attr = self.gatherAttributes # omitting () results in infinite recursion
    return '[Class: %s]\n%s' % (self.__class__.__name__, attr)
  

文件"某些文件夹/ classtools.py",第18行,在__repr __

return '[Class: %s]\n%s' % (self.__class__.__name__, attr)
     

[前一行重复244次]

     

RecursionError:调用Python对象时超出了最大递归深度

我尝试调试但无法找到此行为的确切原因。即使我意外地离开了括号,也应该打印<function object ...>对吗?

为什么在这种情况下它会在__repr__中调用自己?

提前致谢。

编辑:测试代码如下。

if __name__ == '__main__':
    class TopTest(AttributeDisplay):
        count = 0
        def __init__(self):
            self.attr1 = TopTest.count
            self.attr2 = TopTest.count+1
            TopTest.count += 2

    class SubTest(TopTest):
        pass

    def test():
        t1, t2 = TopTest(), SubTest()
        print(t1)
        print(t2)

    test()

1 个答案:

答案 0 :(得分:3)

这是因为绑定方法的repr包含它绑定的对象:

>>> class C:
...     def __repr__(self):
...         return '<repr here!>'
...     def x(self): pass
... 
>>> C().x
<bound method C.x of <repr here!>>
>>> str(C().x)
'<bound method C.x of <repr here!>>'

请注意,我在这里做了几次飞跃 - 这里是:

  • '%s' % x大致相当于str(x)
  • 当某些内容未定义__str__时,它会回退到__repr__(方法描述符就是这种情况)

在检索类的repr时,你最终得到了这个循环:

  • AttributeDisplay.__repr__ =&gt;
  • AttributeDisplay.gatherAttributes.__repr__ =&gt;
  • AttributeDisplay.__repr__(作为绑定方法repr一部分的类的repr)=&gt;
  • ...