最近我阅读了关于 Python 描述符的官方 HOW-TO,它实际上来自于Raymond Hettinger 很久以前写的一篇文章。但读了几遍后,我仍然对它的某些部分感到困惑。我将引用一些段落,然后是我的困惑和问题。
如果实例的字典中有一个与数据描述符同名的条目,则数据描述符优先。如果实例的字典具有与非数据描述符同名的条目,则字典条目优先。
- 上课也是这样吗?如果一个类的字典有一个与数据/非数据描述符同名的条目,那么它的优先级链是什么?
对于物体来说,机器在
object.__getattribute__()
其中转化b.x
为type(b).__dict__['x'].__get__(b, type(b))
。该实现通过优先链进行工作,该优先链赋予数据描述符优先于实例变量,实例变量优先于非数据描述符,并分配最低优先级(__getattr__()
如果提供)。对于类,机器在
type.__getattribute__()
其中转换B.x
为B.__dict__['x'].__get__(None, B)
.
- 上面两段讲述了在属性访问时自动调用描述符的过程。
b.x
它列出了实例 ( ) 和类 ( )访问属性之间的区别B.x
。但是,这是我的困惑:- 如果类或实例的属性不是描述符,那么转换(即转换
b.x
成type(b).__dict__['x'].__get__(b, type(b))
和B.x
成B.__dict__['x'].__get__(None, B)
)还会继续吗?在此类或实例的字典中直接返回属性是否更简单? - 如果一个实例的字典中有一个与非数据描述符同名的条目,根据第一个引号中的优先规则,字典条目优先,这时候转换还会继续吗?还是只返回其dict中的值?
- 如果类或实例的属性不是描述符,那么转换(即转换
非数据描述符提供了一种简单的机制,可以将通常的绑定函数模式更改为方法。
- 是否选择了非数据描述符,因为函数/方法只能获取,但不能设置?
- 将函数绑定到方法的底层机制是什么?由于类字典将方法存储为函数,如果我们分别使用类及其实例调用相同的方法,底层函数如何判断它的第一个参数是否应该是self呢?
函数有一个
__get__()
方法,因此当作为属性访问时它们可以转换为方法。非数据描述符将obj.f(*args)
调用转换为f(obj, *args)
. 调用klass.f(*args)
变为 f(*args)。
- 非数据描述符如何将
obj.f(*args)
调用转换为f(obj, *args)
? - 非数据描述符如何将
klass.f(*args)
调用转换为f(*args)
? - 上述两种转换的底层机制是什么?为什么类和实例之间存在差异?
__get__()
在上述情况下角色方法的作用是什么?