Python 属性访问错误

2 投票
4 回答
1878 浏览
提问于 2025-04-16 14:21

我正在尝试在一个类中自定义属性访问(使用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 个回答

0

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
1

__getattribute__() 这个方法是默认的,所以它在访问 self.attr2 时,实际上是直接去找这个属性,而不是去找 self.data['attr2'] 里的内容。

1
So if __getattribute__() is raising an AttributeError, then why isn't __getattr__() being called and returning the proper value?

这句话的意思是,只有在 Python 正常访问属性的时候,才会自动调用 __getattribute__,如果你自己去调用 __getattribute__,就不在这个范围内。简单来说,你应该几乎不要自己去调用那种形式的 Python 方法,比如 __foo__。这些方法是用来实现一些其他操作所依赖的行为的。

撰写回答