理解__getattribute__

时间:2014-04-10 11:19:08

标签: python python-2.7 attributes

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次(直到达到递归深度)。问题是为什么,不应该涉及任何递归,我正在调用object.__getattribute__而不是self.__getattribute__

1 个答案:

答案 0 :(得分:2)

__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__处理程序中触发{{1}}消息。