如何解释关于__getattribute __,__ getattr__的'怪异'结果?

时间:2014-07-25 08:42:00

标签: python

class B(object):
"""new style class"""

    def __getattribute__(self, name):
        print '__getattribute__ called'
        return super(B, self).__getattribute__(name)

    def __getattr__(self, name):
        print '__getattr__ called'

    def __setattr__(self, name, value):
        print '__setattr__ called'
        if name in ['forbid', 'refuse']:
            raise AttributeError('Attribute name invalid!')
        else:
            return super(B, self).__setattr__(name, value)

B类定义如上,接下来我尝试对__getattr__,__getattribute__进行一些测试:

b = B()
setattr(b, 'test', 100)

print b.__dict__
print b.__getattribute__('__dict__')
print b.__getattr__('__dict__')
print getattr(b, '__dict__')

最后结果是:

__getattribute__ called
{'test': 100}
__getattribute__ called
__getattribute__ called
{'test': 100}
__getattribute__ called
__getattr__ called
None
__getattribute__ called
{'test': 100}

这是我的问题:

1. print b.__getattribute__('__dict__')两次调用__getattribute__,为什么?

2. print b.__getattr__('__dict__')首先调用__getattribute__,然后调用__getattr__?为什么还没有?

上面的结果对我来说似乎很奇怪。我真的不明白这些方法是如何运作的。任何建议或建议都值得赞赏。谢谢!

1 个答案:

答案 0 :(得分:3)

  1. 执行__getattribute__时,第一次b.__getattribute__来电已完成。你想获得名为__getattribute__的属性(是的,我知道这听起来很漂亮)。当您请求名为__getattribute__的属性时,会调用__getattribute__并在结果中获得__getattribute__方法。然后,您只需拨打__getattribute__方法 - 这是__getattribute__

  2. 的第二次调用
  3. b.__getattr__调用__getattribute__来获取名为__getattr__的属性(是的,我知道)。您获得__getattr__方法作为回报。然后调用__getattr__方法。它不会明确地返回任何内容,这意味着它会隐式返回None。

  4. 这是您看到some_obj_of_class_B.some_method()时发生的简化版本:

      调用
    • __getattribute__来获取名为some_method的属性。 __getattribute__打印'我被叫了!'并将其工作委托给object.__getattribute__(我认为,检查some_obj_of_class_B' s __dict__,检查其类__dict__,基类__dict__,处理描述符等。希望object.__getattribute__返回some_method(希望是一个函数,或者更确切地说是一个绑定方法)
    • 调用此函数/绑定方法。在您的情况下,绑定方法本身是__getattribute__。这就是它调用两次的原因。