getattr(foo, 'bar')(基本上是foo.bar)调用__getattribute__,然后可以在以下情况下调用__getattr__(如果存在):
-
AttributeError 由 __getattribute__ 提出
-
__getattribute__ 明确调用它
来自docs:
如果该类还定义了__getattr__(),则不会调用后者
除非__getattribute__() 明确调用它或引发
AttributeError.
如果您不想在随机属性访问中引发属性错误,定义__getattr__ 会很有用。 Mock library 就是一个很好的例子。
>>> from unittest.mock import Mock
>>> m = Mock()
>>> m.foo.bar.spam
<Mock name='mock.foo.bar.spam' id='4367274280'>
如果您不想一直定义__getattr__,也不想一直处理AttributeError,那么您可以使用getattr() 的3 参数形式在未找到属性时返回默认值或使用hasattr 来检查它是否存在。
>> getattr([], 'foo')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-60-f1834c32d3ce> in <module>()
----> 1 getattr([], 'foo')
AttributeError: 'list' object has no attribute 'foo'
>>> getattr([], 'foo', 'default')
'default'
演示:
class A:
def __getattr__(self, attr):
print('Inside A.__getattr__')
return 'eggs'
print(A().foo)
输出:
Inside A.__getattr__
eggs
请注意,数据模型文档指出它为object.__getattr__,但这并不意味着它们存在于内置object 类型中。相反,它们通常可以存在于任何对象上。在这种情况下,对象是一种类型,因为 dunder 方法是在对象的类型上查找的。p>