考虑以下:
class A(object):
def __init__(self):
print 'Hello!'
def foo(self):
print 'Foo!'
def __getattribute__(self, att):
raise AttributeError()
a = A() # Works, prints "Hello!"
a.foo() # throws AttributeError as expected
__getattribute__的实现显然无法完成所有查找.我的问题:
>为什么仍然可以实例化一个对象?我原本期望__init__方法本身的查找也会失败.
>不受__getattribute__约束的属性列表是什么?
最佳答案
The implementation of
__getattribute__
obviously fails all lookups
让我们说它失败了所有的香草查找.
那么__getattribute__本身是如何首先被调用的,因为它也是类的一个属性?
属性将引用点后面的任何名称.因此,要获取类实例的属性,当您尝试访问该属性(通过点引用)时,将无条件地召唤__getattribute__.
然而,像__init__这样的神奇方法是语言构造的一部分,因此不会直接调用(通过点引用),因为它们是作为语言的一部分实现的.
Why is it still possible to instantiate an object?
当你这样做时:
a = A()
__init__方法在幕后调用,但不是通过vanilla查找.语言处理这个.同样适用于其他方法,如__setattr __,__ delattr __,__ getattribute__以及其他方法.
但如果你直接调用__init__:
a.__init__()
这会引起错误.呃,这没有任何意义,因为课程已经初始化了.
更巧妙的是,如果您尝试通过点引用从类实例访问__getattribute__:
a.__getattribute__
它也会引发一个AttributeError;尝试在属性__getattribute__上查找同一方法的语言调用,但失败并出现错误.
What’s the list of attributes that are not subject to
__getattribute__
?
总之,当您尝试通过点引用访问任何属性时,__ getattribute__会播放.只要您不尝试显式调用魔术方法,就不会调用__getattribute__.