__getattribute__
每当发生属性访问时都会调用。
class Foo(object):
def __init__(self, a):
self.a = 1
def __getattribute__(self, attr):
try:
return self.__dict__[attr]
except KeyError:
return 'default'
f = Foo(1)
f.a
这将导致无限递归。罪魁祸首是排队return self.__dict__[attr]
。让我们假装(这与事实很接近)所有属性都存储在self.__dict__
名称中并可用。线
f.a
尝试访问的a
属性f
。这叫f.__getattribute__('a')
。__getattribute__
然后尝试加载self.__dict__
。__dict__
是的属性,self == f
因此python调用f.__getattribute__('__dict__')
再次尝试访问属性'__dict__
'。这是无限递归。
如果__getattr__
曾经使用过,那么
- 它永远不会运行,因为
f
具有a
属性。
- 如果它已经运行((假设您要
f.b
)),则不会调用__dict__
它,因为它已经存在,并且__getattr__
仅当所有其他查找属性的方法均失败时才被调用。
编写上述类的“正确”方法__getattribute__
是
class Foo(object):
# Same __init__
def __getattribute__(self, attr):
return super(Foo, self).__getattribute__(attr)
super(Foo, self).__getattribute__(attr)
将__getattribute__
“最近”超类的方法(self
通常是该类的“方法解析顺序”中的下一个类)绑定到当前对象,然后调用它并让其完成工作。
通过使用__getattr__
python 可以在没有找到属性之前将其正常处理,从而避免了所有这些麻烦。到那时,Python将控制权交给您的__getattr__
方法,并让它提出一些建议。
还值得注意的是,您可以使用进行无限递归__getattr__
。
class Foo(object):
def __getattr__(self, attr):
return self.attr
我将把它留作练习。