pyhton __getattribute__返回类变量属性时的RecursionError

问题描述 投票:0回答:1

为什么Foo2会导致无限递归调用getattr中的类变量的__getattribute__,但是Foo可以很好地在__getattr__中进行相同的调用?关于如何使Foo2正常工作的任何建议?

class Foobar(object):
    def __init__(self):
        super().__init__()
        self.bar = 5

    def getbar(self):
        return self.bar


class Foo(object):
    def __init__(self):
        super().__init__()
        self.__foo = Foobar()

    def __getattr__(self, attr):
        return getattr(self.__foo, attr)


class Foo2(object):
    def __init__(self):
        super().__init__()
        self.__foo = Foobar()

    def __getattribute__(self, attr):
        try:
            return getattr(self.__foo, attr)
        except AttributeError:
            super().__getattribute__(attr)


if __name__ == '__main__':
    foo = Foo()
    foo2 = Foo2()
    print(foo.bar, foo.getbar())  # Works as expected
    try:
        print(foo2.bar, foo2.getbar())  # Doesn't work
    except RecursionError:
        print('Why does Foo2 result in RecursionError. How to fix?')

设置:Windows 10,Python 3.7

python python-3.x recursion getattr getattribute
1个回答
0
投票

__getattribute__方法被无条件调用,以查找对象上的所有属性,不仅查找不存在的属性(__getattr__会执行此操作)。当您在实现中执行self.__foo时,您会递归,因为__foo是我们试图在对象上查找的另一个属性。

为避免此问题,您需要调用父级的__getattribute__方法以在__getattribute__方法中获取所有自己的属性:

def __getattribute__(self, attr):
    try:
        return getattr(super().__getattribute__("_Foo__foo"), attr)
    except AttributeError:
        super().__getattribute__(attr)

请注意,我必须手动将名称修饰应用于__foo属性,因为我们需要将名称作为字符串传递给super().__getattribute__。这可能表明您不应该一开始就进行整顿。带有单个下划线的名称可能是一个更好的选择。

© www.soinside.com 2019 - 2024. All rights reserved.