我的代码中有一个错误(类似于下面的错误),但是结果对我来说似乎很奇怪。有人可以给我解释一下名称为“ hello”的getattr是如何被调用的吗?
class A(object):
def __getattr__(self, name):
print name
assert name != 'hello'
return self.hello
class C(object):
def __init__(self):
class B(A):
@property
def hello(self_):
return self.durp
self.b = B()
c = C()
print c.b.bang
Run Code Online (Sandbox Code Playgroud)
输出为:
bang
hello
Traceback (most recent call last):
File "test.py", line 17, in <module>
print c.b.bang
File "test.py", line 5, in __getattr__
return self.hello
File "test.py", line 4, in __getattr__
assert name != 'hello'
AssertionError
shell returned 1
Run Code Online (Sandbox Code Playgroud)
我当然知道C中没有durp属性(这是我所说的错误)。但是,我不希望__getattr__用hello作为字符串来调用它。我觉得我不了解有关__getattr__工作方式的基本知识。
__getattr__通过“常用方法”访问属性失败时调用。Python知道“常规方法”是否失败的方式是引发AttributeError。但是,它无法确定是在尝试获取要获取的原始属性时引发了AttributeError,还是在该过程中访问了某些其他属性。所以这是发生了什么:
c.b.bang__getattr__称为。__getattr__试图得到self.hellohello,其值为属性self.hello,Python运行该hello属性。hello属性会尝试访问一个不存在的属性durp。这引发了AttributeErrorself.hello,Python认为通过“通常的方法”没有可用的此类属性。因此__getattr__,它以“ hello”作为参数进行调用。这种行为令人困惑,但是从根本上来说,这是Python中属性查找如何工作的不可避免的副作用。知道“常规属性查找无效”的唯一方法是引发了AttributeError。有一个关于此的Python错误,显然人们仍在研究,但到目前为止尚无真正的解决方案。