Python 属性访问错误
我正在尝试在一个类中自定义属性访问(使用python2.7)。假设我定义了以下这个类:
class testAttrAccess(object):
def __init__(self):
self.data = {"attr1":"value1","attr2":"value2"}
def __getattr__(self,name):
try:
return self.data[name]
except KeyError:
pass
raise AttributeError
然后我得到了:
In [85]: a = testAttrAccess()
In [86]: a.attr2
Out[86]: 'value2'
In [87]: a.__getattr__('attr2')
Out[87]: 'value2'
In [88]: a.__getattribute__('attr2')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/Users/laserson/temp/<ipython console> in <module>()
AttributeError: 'testAttrAccess' object has no attribute 'attr2'
但是,根据python的文档
如果这个类还定义了
__getattr__()
,那么除非__getattribute__()
显式调用它,或者抛出一个AttributeError
,否则__getattr__()
是不会被调用的。
所以如果 __getattribute__()
抛出了一个 AttributeError
,那为什么 __getattr__()
没有被调用并返回正确的值呢?
4 个回答
a.__getattr__
这个方法只有在找不到属性的时候才会被调用,也就是说,如果你在对象 a
的属性字典 a.__dict__
中找不到你要的属性,才会去用这个方法。
而 a.__getattribute__
这个方法在任何情况下都会被调用,只要它被定义了。
你可能知道,a.__getattribute__(attr)
其实是 type(a).__getattribute__(a, attr)
的一种简写方式,但因为这个方法在 testAttrAccess
中没有被定义,所以会调用父类的方法 object.__getattribute__(a, attr)
。根据你的结果,我们可以得出结论:不是 object.__getattribute__
调用了 __getattr__
,可能是解释器自己处理了这个。
你可以通过这样修改你的程序来让它正常工作:
class testAttrAccess(object):
def __init__(self):
self.data = {"attr1": "value1", "attr2": "value2"}
def __getattribute__(self, name):
try:
return object.__getattribute__(self, name)
except AttributeError:
if name == "__getattr__":
return object.__getattribute__(self, "__getattribute__")
try:
return object.__getattribute__(self, "data")[name]
except KeyError:
raise AttributeError
a = testAttrAccess()
print a.attr2
print a.__getattr__('attr2')
print a.__getattribute__('attr2')
print a.qwerty
输出结果:
value2 value2 value2 Traceback (most recent call last): File "test.py", line 20, in print a.qwerty File "test.py", line 13, in __getattribute__ raise AttributeError AttributeError
__getattribute__()
这个方法是默认的,所以它在访问 self.attr2
时,实际上是直接去找这个属性,而不是去找 self.data['attr2']
里的内容。
So if __getattribute__() is raising an AttributeError, then why isn't __getattr__() being called and returning the proper value?
这句话的意思是,只有在 Python 正常访问属性的时候,才会自动调用 __getattribute__
,如果你自己去调用 __getattribute__
,就不在这个范围内。简单来说,你应该几乎不要自己去调用那种形式的 Python 方法,比如 __foo__
。这些方法是用来实现一些其他操作所依赖的行为的。