在给定的类中,在给定的情况下,选择实现哪一个的一般经验法则是什么?
我已经阅读了这些文档,因此理解了它们之间的区别。相反,我正在寻找如何最好地将它们的使用集成到我的工作流程中的指导,以便更好地注意到使用它们的更微妙的机会,以及何时使用它们。这类事情。有问题的方法是(据我所知):
## fallback
__getattr__
__setattr__
__delattr__
## full control
__getattribute__
##(no __setattribute__ ? What's the deal there?)
## (the descriptor protocol)
__get__
__set__
__delete__
2条答案
按热度按时间ecr0jaav1#
__setattribute__
不存在,因为__setattr__
* 总是 * 被调用。__getattr__
仅在通过正常通道(由__getattribute__
提供,因此该函数同样总是被调用)查找属性失败时才为f.x
调用。描述符协议与其他协议稍微正交。
以下是正确的:
__getattribute__
,则f.x
将调用f.__getattribute__('x')
。__getattr__
,则f.x
不会调用f.__getattr__('x')
。__getattr__
,则f.y
将调用f.__getattr__('y')
;如果定义了__getattribute__
,则f.__getattribute__('y')
将调用f.__getattribute__('y')
。描述符是由一个属性调用的,而不是为一个属性调用的。即:
现在,
f.x
将导致调用type(f).__dict__['x'].__get__
,而f.x = 3
将调用type(f).__dict__['x'].__set__(3)
。也就是说,
Foo.__getattr__
和Foo.__getattribute__
将用于查找f.x
* 引用的内容 *;一旦你有了它,f.x
会产生type(f.x).__get__()
的结果(如果定义了),而f.x = y
会调用f.x.__set__(y)
(如果定义了)。(The上面对
__get__
和__set__
的调用只是大致正确的,因为我已经省略了__get__
和__set__
实际接收的参数的细节,但这应该足以解释__get__
和__getattr[ibute]__
之间的差异。换句话说,如果
MyDescriptor
没有定义__get__
,那么f.x
将简单地返回MyDescriptor
的示例。piztneat2#
关于
__getattr__
与__getattribute__
,请参见Difference between getattr vs getattribute示例。__get__
并没有真正相关。我将引用official documentation for the descriptor protocol在这里:属性访问的默认行为是从对象的字典中获取、设置或删除属性。例如,a.x有一个查找链,从
a.__dict__['x']
开始,然后是type(a).__dict__['x']
,并继续通过type(a)
的基类(不包括元类)。如果查找的值是定义描述符方法之一的对象,那么Python可能会覆盖默认行为,转而调用描述符方法。这在优先级链中的位置取决于定义了哪些描述符方法。__get__
的目的是控制通过“查找链”找到a.x
后发生的事情(例如,创建一个方法对象,而不是返回通过type(a).__dict__['x']
找到的普通函数);__getattr__
和__getattribute__
的目的是改变查找链本身。这里没有
__setattribute__
,因为只有一种方法可以真正设置对象的属性,你可能想在设置属性时“神奇地”发生其他事情;但是__setattr__
涵盖了这一点。__setattribute__
不可能提供任何__setattr__
还没有的功能。然而,在绝大多数情况下,最好的答案是甚至不要考虑使用这些工具。首先看看更高级别的抽象,如
property
s、classmethod
s和staticmethod
s。如果您认为需要这样的专用工具,而自己又不能弄清楚,那么很有可能您的想法是错误的;但无论如何,在这种情况下,最好发布一个更具体的问题。