理解 __getattribute__
class Shadow(object):
pass
class Test(object):
a = 1
b = 2
_shadow = Shadow()
def __getattribute__(self, name):
try:
return object.__getattribute__(self._shadow, name)
except: print "not shadowed"
return object.__getattribute__(self, name)
在上面的代码中,我想实现以下功能:
>>>t = Test()
>>>t.a
1
>>>t._shadow.a = 17
>>>t.a
17
>>>t.b
2
这段代码是可以运行的,但它会打印“M”次“not shadowed”(直到达到递归的深度)。我的问题是,为什么会这样?因为这里不应该有递归,我调用的是 object.__getattribute__
,而不是 self.__getattribute__
。
1 个回答
3
__getattribute__
是在访问任何属性时都会被调用的,包括访问 self._shadow
。但是因为你重写了 __getattribute__
,所以访问 self._shadow
时会导致无限循环。
解决这个问题的方法是使用 object.__getattribute__
,或者更好的是,使用 super(Test, self).__getattribute__
来获取 _shadow
属性:
class Test(object):
a = 1
b = 2
_shadow = Shadow()
def __getattribute__(self, name):
shadow = super(Test, self).__getattribute__('_shadow')
try:
return getattr(shadow, name)
except AttributeError:
print "not shadowed"
return super(Test, self).__getattribute__(name)
在访问影子对象的属性时,不需要使用 object.__getattribute__
。不要像抓宝可梦那样处理异常(你不想捕捉所有的);在这里只捕捉特定的 AttributeError
异常。
示例:
>>> t = Test()
>>> t.a
not shadowed
1
>>> t._shadow.a = 42
not shadowed
>>> t.a
42
注意,这里访问 t._shadow
也会触发 'not shadowed'
的消息,因为它会经过 __getattribute__
的处理。