[英]Why are there two magic methods to access object attributes in Python?
I'm studying Python's object attribute access patterns ( Descriptor HowTo Guide and Data model docs ). 我正在研究Python的对象属性访问模式( 描述符方法指南和数据模型docs )。 The thing I can't clearly understand is why did Guido provide both
__getattr__
and __getattribute__
methods for objects? 我不清楚的是Guido为什么同时为对象提供
__getattr__
和__getattribute__
方法? They both do exactly the same thing but are invoked differently. 它们都做完全相同的事情,但是调用方式不同。
For me this seems as if a badly designed class could be fixed by even worse design. 对我来说,这似乎可以通过更差的设计来修复设计不好的类。 I mean, if something needs refactoring, it should not be "glued" with magic methods being called with high or higher precedence.
我的意思是,如果某些东西需要重构,则不应以高优先级或更高优先级调用魔术方法将其“粘合”。
The question is - why are there two similar methods if one would be perfectly enough? 问题是-如果一种方法足够完美,为什么会有两种类似的方法?
I'm not referring to descriptors, which are something different. 我不是指描述符,这是有所不同的。
The two methods serve different purposes. 两种方法有不同的用途。
__getattribute__
is called for all attribute access. 所有属性访问均调用
__getattribute__
。 __getattr__
is only called by __getattribute__
if the latter failed to locate an attribute. __getattr__
仅在__getattribute__
找不到属性时才被调用。
It is far easier to implement a correct __getattr__
method than it is to implement a __getattribute__
replacement. 实现正确的
__getattr__
方法要比实现__getattribute__
替换容易得多。 Sure, you can do without __getattr__
in that scenario, but that also would make implementing the common use-case all the harder. 当然,在那种情况下,您可以不用
__getattr__
来做,但这也将使实现通用用例变得更加困难。
For example, in __getattr__
you can easily access other, existing attributes on self
; 例如,在
__getattr__
您可以轻松地访问self
上的其他现有属性; if you need self.bar
to fulfil a dynamic attribute, then that's easy to do so. 如果您需要
self.bar
来实现动态属性,那么这样做很容易。 In __getattribute__
you cannot access anything on self
with normal attribute access, as that is all handled by __getattribute__
methods; 在
__getattribute__
您无法通过常规属性访问self
上的任何内容,因为所有这些都由__getattribute__
方法处理; you'd end up in an infinite recursion if you tried. 如果尝试,最终将导致无限递归。 Instead, all attribute access within that method has to use
super(ClassName, self).__getattribute__(name)
calls. 相反,该方法内的所有属性访问都必须使用
super(ClassName, self).__getattribute__(name)
调用。
Note that __getattribute__
is always implemented; 注意
__getattribute__
总是被实现; object.__getattribute__
provides the default implementation. object.__getattribute__
提供默认的实现。 Use __getattribute__
only if you need to intercept the default behaviour; 仅在需要拦截默认行为时才使用
__getattribute__
; say you need to override existing attributes in special circumstances, or override the normal descriptor behaviour . 说您需要在特殊情况下覆盖现有属性,或覆盖常规描述符行为 。 See Understanding __getattribute__ for an example where existing attribute access is being overridden.
有关覆盖现有属性访问的示例,请参见了解__getattribute__ 。
Use __getattr__
for everything else; 使用
__getattr__
进行其他操作; eg dynamic attributes where those attributes do not already exist on the object. 例如动态属性,这些属性在对象上尚不存在。 Say, you are providing a proxy class, where most attribute access is passed on to the wrapped object:
假设您要提供一个代理类,其中大多数属性访问都传递给包装的对象:
class Proxy(object):
def __init__(self, wrapped):
self._wrapped = wrapped
def foo(self):
return self._wrapped.foo() + 42
def __getattr__(self, name):
return getattr(self._wrapped, name)
Here _wrapped
and foo
are found directly on Proxy()
, but if you tried to access bar
, an attribute that does not exist on the Proxy
class, __getattr__
is called instead which translates that as attribute access on self._wrapped
. 在这里
_wrapped
和foo
直接在Proxy()
上找到,但是如果您尝试访问bar
,则该属性在Proxy
类上不存在,而是调用__getattr__
,将其转换为对self._wrapped
属性访问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.