Python 从“理解描述符示例”;“如何”的描述符;文章
我正试图把我的头脑围绕在描述符的概念上,但我最近没有成功。这一描述对我有很大帮助,同时也让我感到困惑。我在这里与这个例子作斗争 关于为什么Python 从“理解描述符示例”;“如何”的描述符;文章,python,descriptor,python-descriptors,Python,Descriptor,Python Descriptors,我正试图把我的头脑围绕在描述符的概念上,但我最近没有成功。这一描述对我有很大帮助,同时也让我感到困惑。我在这里与这个例子作斗争 关于为什么m.x调用def\uu-get\uu(self、obj、objtype): 我相信我之所以在这方面苦苦挣扎,是因为我对文章中的以下陈述感到困惑 调用的细节取决于obj是对象还是对象 班级。对于对象,机器位于对象中。\uuu getattribute\uuuu() 它将b.x转换为类型(b)。\uuuuu dict\uuuuu['x']。\uuuu get\uu
m.x
调用def\uu-get\uu(self、obj、objtype):
我相信我之所以在这方面苦苦挣扎,是因为我对文章中的以下陈述感到困惑
调用的细节取决于obj是对象还是对象
班级。对于对象,机器位于对象中。\uuu getattribute\uuuu()
它将b.x
转换为类型(b)。\uuuuu dict\uuuuu['x']。\uuuu get\uuuuuu(b,类型(b))
。
该实现通过提供数据的优先级链工作
描述符优先于实例变量,实例变量
优先级高于非数据描述符,并将最低优先级分配给
\uuuu getattr\uuuuu()
如果提供
我不确定作者这里所说的对象或类是什么意思。对象是否表示类的实例?我理解,当我们执行instance.var
时,python会在内部执行实例。在那之后我有点失去了它。有人能解释一下这个例子是如何工作的吗。定义def\uu get\uu(self、obj、objtype):
是如何用m.x
调用的。如果有人能澄清这一点,我将不胜感激。是的,作者所说的对象是一个实例,而不是一个类。区别来自描述者居住的地方;描述符是在类上定义的,因此当直接在类上访问该描述符时,将遵循与在类实例上访问该描述符时不同的路径
在您的示例中,m
是一个实例。该实例本身没有属性m
(m中的'x'。\uu dict\uuu
为False
)。Python还查看type(m)
来解析该属性,而type(m)
这里是MyClass
<代码>MyClass中的“x”。\uuuu dict\uuuu
是True
,并且MyClass.\uu dict\uuuu['x']。\uu get\uuuu
存在,因此Python现在知道该对象是一个描述符
因此,因为没有m.\uuu dict\uuuuuuuu['x']
,但是有一个type(m)。\uu dict\uuuuuu['x'].\uu get\uuuuuuuuuu
,这个方法是用m
和type(m)
作为参数调用的,导致type(m)。\uu dict\uuuuuuuuuuuuuuuuu['x']
如果MyClass中的'x.\uuuuu dict\uuuuu
为true,但MyClass.\uuuu dict\uuuuuu['x'].\uuu get\uuuuuuuu
不存在(因此该对象不是描述符对象),则将直接返回MyClass.\uuuu dict\uuuuuu['x']
如果您尝试将x
属性也添加到实例中,情况会变得更有趣。在这种情况下,如果存在MyClass.\uuuuu dict.\uuuuu['x']。\uuuu set.\uuuu
或MyClass.\uuuu dict.\uuuu['x']。\uuuu delete.\uuuu
则很重要,使描述符成为数据描述符。数据描述符总是在平局中获胜。因此,如果MyClass.\uuu dict.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。Python甚至不会去寻找它
但是,如果类上的描述符对象上没有\uuuuuu set\uuuuuuuu
或\uuuu delete\uuuuuuuuuuu
方法,则m.\uuuuu dict\uuuuuuu['x']
获胜并返回。在这种情况下,描述符是一个常规的非数据描述符,它会丢失给instance属性
最后但并非最不重要的一点是,如果类型(m)中的'x.\uuu dict\uuu
为false(类上没有对象),则返回m.\uu dict\uu['m']
。描述符协议仅应用于类上的对象,而不应用于实例上的属性。是的,按对象而言,作者指的是实例,而不是类。区别来自描述者居住的地方;描述符是在类上定义的,因此当直接在类上访问该描述符时,将遵循与在类实例上访问该描述符时不同的路径
在您的示例中,m
是一个实例。该实例本身没有属性m
(m中的'x'。\uu dict\uuu
为False
)。Python还查看type(m)
来解析该属性,而type(m)
这里是MyClass
<代码>MyClass中的“x”。\uuuu dict\uuuu
是True
,并且MyClass.\uu dict\uuuu['x']。\uu get\uuuu
存在,因此Python现在知道该对象是一个描述符
因此,因为没有m.\uuu dict\uuuuuuuu['x']
,但是有一个type(m)。\uu dict\uuuuuu['x'].\uu get\uuuuuuuuuu
,这个方法是用m
和type(m)
作为参数调用的,导致type(m)。\uu dict\uuuuuuuuuuuuuuuuu['x']
如果MyClass中的'x.\uuuuu dict\uuuuu
为true,但MyClass.\uuuu dict\uuuuuu['x'].\uuu get\uuuuuuuu
不存在(因此该对象不是描述符对象),则将直接返回MyClass.\uuuu dict\uuuuuu['x']
如果您尝试将x
属性也添加到实例中,情况会变得更有趣。在这种情况下,如果存在MyClass.\uuuuu dict.\uuuuu['x']。\uuuu set.\uuuu
或MyClass.\uuuu dict.\uuuu['x']。\uuuu delete.\uuuu
则很重要,使描述符成为数据描述符。数据描述符总是在平局中获胜。因此,如果MyClass.\uuu dict.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。Python甚至不会去寻找它
但是,如果类上的描述符对象上没有\uuuu set\uuu
或\uu delete\uuuu
方法,则m
class RevealAccess(object):
def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name
def __get__(self, obj, objtype):
print('Retrieving', self.name)
return self.val
def __set__(self, obj, val):
print('Updating', self.name)
self.val = val
>>> class MyClass(object):
... x = RevealAccess(10, 'var "x"')
... y = 5
...
>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
m.x
type(m).__dict__['x'].__get__(m, type(m))
MyClass.__dict__['x'].__get__(m, MyClass)
RevealAccess(10, 'var "x"').__get__(m, MyClass)