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

  1. In type(instance).__dict__-如果存在给定名称的数据描述符,则返回其__get__方法调用
  2. instance.__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__书写方式,它在instance上设置了一种神奇的方法.

这在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相关问答推荐

如何从具有多个嵌入选项卡的网页中Web抓取td类元素

如何在BeautifulSoup中链接Find()方法并处理无?

仿制药的类型铸造

根据另一列中的nan重置值后重新加权Pandas列

从numpy数组和参数创建收件箱

组/群集按字符串中的子字符串或子字符串中的字符串轮询数据框

Django—cte给出:QuerySet对象没有属性with_cte''''

如何从需要点击/切换的网页中提取表格?

Maya Python脚本将纹理应用于所有对象,而不是选定对象

在代码执行后关闭ChromeDriver窗口

如何按row_id/row_number过滤数据帧

如何在FastAPI中替换Pydantic的constr,以便在BaseModel之外使用?'

在Python中控制列表中的数据步长

比较两个有条件的数据帧并删除所有不合格的数据帧

如何在Python中解析特定的文本,这些文本包含了同一行中的所有内容,

根据过滤后的牛郎星图表中的数据计算新系列

如何将列表从a迭代到z-以抓取数据并将其转换为DataFrame?

对于数组中的所有元素,Pandas SELECT行都具有值

极点:在固定点扩展窗口

迭代工具组合不会输出大于3的序列