Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在类上设置描述符会覆盖描述符?_Python_Cpython_Python Descriptors - Fatal编程技术网

Python 为什么在类上设置描述符会覆盖描述符?

Python 为什么在类上设置描述符会覆盖描述符?,python,cpython,python-descriptors,Python,Cpython,Python Descriptors,简单复制: class VocalDescriptor(对象): 定义获取(self、obj、objtype): 打印(''uuuu获取,obj={},objtype={}'。格式(obj,objtype)) 定义设置(自身、对象、值): 打印(“设置”) B类(对象): v=语音脚本编写器() B.v打印“\uu获取,obj=None,objtype=” B.v=3#不打印“uuu set_uuu”,显然不触发描述符 B.v#不打印任何内容,我们重写了描述符 这个问题有一个答案,但重复的问题

简单复制:

class VocalDescriptor(对象):
定义获取(self、obj、objtype):
打印(''uuuu获取,obj={},objtype={}'。格式(obj,objtype))
定义设置(自身、对象、值):
打印(“设置”)
B类(对象):
v=语音脚本编写器()
B.v打印“\uu获取,obj=None,objtype=”
B.v=3#不打印“uuu set_uuu”,显然不触发描述符
B.v#不打印任何内容,我们重写了描述符
这个问题有一个答案,但重复的问题没有得到回答,作为一个学习练习,我对CPython源代码进行了更多的挖掘。警告:我进入杂草丛中。我真的希望能得到你的帮助。为了我自己和未来读者的利益,我试图尽可能明确地追踪我所看到的电话

我已经看到很多墨水溢出到应用于描述符的
\uuuu getattribute\uuuu
行为上,例如查找优先级。在
下面的Python代码片段中,对于类,机器是类型的。uuu getattribute_uuu()…
在我看来大致与
类型中的对应内容一致,我当时通过查看找到了这一点。而
B.v
最初打印
\uuuu get\uuuuuu,obj=None,objtype=
这一事实对我来说很有意义

我不明白的是,为什么赋值
B.v=3
会盲目地覆盖描述符,而不是触发
v.\uu设置\uuu
?我试着追踪CPython的电话,再次从开始,然后看着,然后看着<代码>键入_setattro
一个薄薄的包装。这就是我困惑的症结所在:
\u PyObject\u genericsetarwithdict
似乎有!!考虑到这一点,我不明白为什么
B.v=3
会盲目地覆盖
v
,而不是触发
v.。\uu设置\uu

免责声明1:我并没有用printfs从源代码中重建Python,所以我不是 完全确定
type_setattro
是在
B.v=3
期间调用的


免责声明2:
VocalDescriptor
无意举例说明“典型”或“推荐”描述符定义。在调用方法时告诉我这是一个冗长的no op。

您正确地认为
B.v=3
只是用一个整数覆盖描述符(它应该是这样的)。在描述符协议中,但是
\uuuuu set\uuuu
被设计为仅作为实例属性调用

对于调用描述符的
B.v=3
,描述符应该在元类上定义,即在
type(B)
上定义

要调用
B
上的描述符,可以使用一个实例:
B()。v=3
将执行此操作

B.v
也调用getter的原因是允许用户自定义
B.v
所做的事情,独立于
B().v
所做的事情。一种常见模式是允许直接访问描述符实例,方法是在使用类属性访问时返回描述符本身:

class VocalDescriptor(object):
    def __get__(self, obj, objtype):
        if obj is None:
            return self
        print('__get__, obj={}, objtype={}'.format(obj, objtype))
    def __set__(self, obj, val):
        print('__set__')
现在
B.v
将返回一些类似
的实例,您可以与之交互。它实际上是描述符对象,定义为类属性,其状态
B.v.\uu dict\uuu
B
的所有实例之间共享

当然,这取决于用户的代码来定义他们想要
B.v
做什么,返回
self
只是常见的模式。A是一个描述符的示例,在这里做了一些不同的事情,请参阅,以获取
classmethod
的纯python实现


与可用于独立自定义
B().v
B.v
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我认为使用相同的描述符来定制
B().v=other
B.v=other
的目标并不常见,也不足以使描述符协议进一步复杂化,特别是因为后者仍然可以使用元类描述符,如上面的
B.v
所示,
B.v=3
简单地用一个整数覆盖描述符是正确的。在描述符协议中,但是
\uuuuu set\uuuu
被设计为仅作为实例属性调用

对于调用描述符的
B.v=3
,描述符应该在元类上定义,即在
type(B)
上定义

要调用
B
上的描述符,可以使用一个实例:
B()。v=3
将执行此操作

B.v
也调用getter的原因是允许用户自定义
B.v
所做的事情,独立于
B().v
所做的事情。一种常见模式是允许直接访问描述符实例,方法是在使用类属性访问时返回描述符本身:

class VocalDescriptor(object):
    def __get__(self, obj, objtype):
        if obj is None:
            return self
        print('__get__, obj={}, objtype={}'.format(obj, objtype))
    def __set__(self, obj, val):
        print('__set__')
现在
B.v
将返回一些类似
的实例,您可以与之交互。它实际上是描述符对象,定义为类属性,其状态
B.v.\uu dict\uuu
B
的所有实例之间共享

当然,这取决于用户的代码来定义他们想要
B.v
做什么,返回
self
只是常见的模式。A是一个描述符的示例,在这里做了一些不同的事情,请参阅,以获取
classmethod
的纯python实现

与可用于独立自定义
B().v
B.v
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我认为使用同一描述符定制
B().v=other
B.v=other
的目标并不常见,也不足以使描述符协议进一步复杂化,特别是