[英]Very strange __getattr__ behavior in python
I had an error in my code (similar to the error below) but the result seems very strange to me. 我的代码中有一个错误(类似于下面的错误),但结果对我来说似乎很奇怪。 Can someone explain to me how getattr is getting called with the name being "hello"?
有人可以给我解释一下名称为“ 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
The output of this is: 输出为:
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
I understand of course that there is no durp property in C (this is the error I speak of). 我当然知道C中没有durp属性(这是我所说的错误)。 However, I would not expect
__getattr__
to be called with hello as the string. 但是,我不希望以hello作为字符串调用
__getattr__
。 I feel like I'm not understanding something fundamental about the way __getattr__
works. 我觉得我不太了解
__getattr__
工作原理。
__getattr__
is called when accessing an attribute via "the usual methods" fails. 通过“常用方法”访问属性失败时,将调用
__getattr__
。 The way Python knows whether "the usual methods" have failed is that an AttributeError is raised. Python知道“常规方法”是否失败的方式是引发AttributeError。 It can't tell, though, whether this AttributeError was raised in trying to get the original attribute you were trying to get, or some other attribute accessed as part of that process.
但是,它无法确定是在尝试获取要获取的原始属性时引发了此AttributeError,还是在该过程中访问了某些其他属性。 So here's what happens:
所以这是发生了什么:
cbbang
cbbang
__getattr__
is called. __getattr__
。 __getattr__
tries to get self.hello
__getattr__
尝试获取self.hello
hello
, whose value is a property hello
,其值是一个属性 self.hello
, Python runs the hello
property. self.hello
,Python运行hello
属性。 hello
property tries to access a nonexistent attribute durp
. hello
属性会尝试访问不存在的属性durp
。 This raises an AttributeError self.hello
, Python thinks there is no such attribute available via "the usual methods". self.hello
引发了AttributeError,所以Python认为没有可通过“常规方法”获得的此类属性。 It therefore calls __getattr__
with "hello" as the argument. __getattr__
。 This behavior is confusing, but is basically an unavoidable side effect of how attribute lookup in Python works. 这种行为令人困惑,但是从根本上来说,这是Python中属性查找如何工作的不可避免的副作用。 The only way to know that "normal attribute lookup didn't work" is that an AttributeError was raised.
知道“常规属性查找无效”的唯一方法是引发了AttributeError。 There is a Python bug about this, which apparently people are still working on, but no real solution exists so far.
有一个关于此的Python错误 ,显然人们仍在研究,但到目前为止尚无真正的解决方案。
return self.hello
in the definition of a.__getattr__
在
a.__getattr__
的定义中return self.hello
a.__getattr__
class A(object):
def __getattr__(self, name):
print name
assert name != 'hello'
return self.hello
triggers a new attribute search, this time with 'hello'
as the value of the name
parameter, which causes your assertion to fail 触发新的属性搜索,这次使用
'hello'
作为name
参数的值,这会导致断言失败
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.