You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何为方法描述符设置__set__函数无法将其转为数据描述符?

Python描述符:动态添加__set__为何无法转为数据描述符?

问题核心

你尝试给类中的方法(本质是function实例,属于非数据描述符)动态添加__set__属性,期望将其转为数据描述符以阻止实例重写该方法,但测试中实例依然能成功赋值并覆盖,问题出在Python判断数据描述符的规则上。

根本原因

Python判断一个对象是否为数据描述符,依据的是该对象的类是否实现了__set__或__delete__方法,而非对象实例本身是否拥有这些属性。

你的测试代码中,A.d是function类的实例,尽管你给这个实例手动添加了__set__属性,但function类本身并没有定义__set__方法。因此Python依然会将其视为非数据描述符,遵循原有的属性访问优先级:实例__dict__中的值会优先于非数据描述符被返回。

当你执行a.d = "value"时,这个值直接存入了a.__dict__,后续访问a.d自然会取到这个值,而非触发描述符的__get__。

正确实现方式

要将方法转为数据描述符,必须自定义一个实现了__get__和__set__的描述符类,用该类的实例替换原有的方法:

class DataDescriptor:
    def __init__(self, func):
        self.func = func
    
    def __get__(self, instance, owner):
        # 模拟原方法的绑定行为
        if instance is None:
            return self
        return self.func.__get__(instance, owner)
    
    def __set__(self, instance, value):
        print("Nothing to see here...")

class A:
    def d(self):
        pass

# 替换原方法为数据描述符实例
A.d = DataDescriptor(A.d)

a = A()
a.d = "value"  # 触发__set__,打印提示
print(a.d)     # 输出绑定方法,而非赋值的"value"

补充验证属性访问顺序

你理解的属性访问顺序是正确的:

    1. 优先查找类__dict__中的数据描述符,调用其__get__
    1. 查找实例__dict__
    1. 查找类__dict__中的非数据描述符,调用其__get__
    1. 最后调用__getattr__

只有当类中的属性是数据描述符时,才能跳过实例__dict__的查找,阻止实例对该属性的重写。

内容的提问来源于stack exchange,提问作者Maciej Sinicki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:52:28