python 在返回类变量属性时__getattribute__递归错误



为什么 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

无条件调用__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__。这可能表明你不应该首先进行重整。具有单个前导下划线的名称可能是更好的选择。

最新更新