python - 为什么为方法描述符设置 __set__ 函数不会使其成为数据描述符?

标签 python python-descriptors

我已经开始阅读有关 Python 中的描述符的内容,并创建了一个小测试来查看属性访问的顺序是否与描述的相同。据我了解,当访问对象的属性时,会按以下顺序查看:

  1. in type(instance).__dict__ - 如果给定名称的数据描述符存在,则返回其__get__方法调用
  2. 实例.__dict__
  3. 如果 type(instance).__dict__ 中存在非数据描述符,则返回 __get__ 方法调用
  4. __getattr__ 被调用。

现在,如果方法是给定类的类型实例的非数据描述符,则通过给定此描述符 __set__ 函数/方法,它将使其成为数据描述符,因此可以覆盖此类函数,例如被阻止或操纵。不幸的是,这不起作用,我的问题很简单:为什么会出现这种情况? Python 是否在类初始化时“标记”数据和非数据描述符,还是我做错了什么?

class A:
    def d(self):
        pass

def __set__(self, instance, value):
    print("Nothing to see here...")



A.__dict__['d'].__set__ = __set__
a = A()
a.d = "value"
print(a.d) # prints "value" instead of <bound method ...>

最佳答案

A.__dict__['d'].__set__ = __set__,在本例中只是一种复杂的编写 A.d.__set__ = __set__ 的方式,正在设置一个魔法实例上的方法。

这在 Python 中不起作用,魔术方法仅在类型上查找。而且你不能在类型上设置它,因为类型只是这里的内置函数类型。

但是,可以动态地将非数据描述符更改为数据描述符:

>>> class MyDescriptor:
...     def __get__(self, instance, owner=None):
...         return 'foo'
... 
>>> class A:
...     f = MyDescriptor()
... 
>>> a = A()
>>> a.f
'foo'
>>> a.f = 'foo2'
>>> a.f
'foo2'
>>> MyDescriptor.__set__ = lambda self, instance, value: None
>>> a.f  # now the descriptor takes precedence again over a.__dict__
'foo'

关于python - 为什么为方法描述符设置 __set__ 函数不会使其成为数据描述符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76863390/

相关文章:

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

在 Windows 10 上安装 python 3.5 Scipy 包

python - 在 Android 上使用 bash shell 打开浏览器后尝试输入搜索数据

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

python - 以声明方式设置类 __name__

python - 带有描述符的类型提示

python - 以声明方式设置类 __name__

python - 以 ASCII 显示树

c++ - 如何将 QGraphicsScene 动画渲染到电影文件中?

python - 在Python中,为什么Hash不检查具有相同哈希和标识的对象的相等性?