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

如何验证Python中这一晦涩的元编程行为是有意设计的?

类与元类同名数据描述符的访问规则解释

这个行为完全符合Python的核心属性查找规则,属于有文档依据的标准行为,可以安全依赖,在所有标准Python实现(CPython、PyPy等)的2.6+版本中表现一致。

核心逻辑拆解

  1. 类的本质:Python中的类本身是元类的实例。比如示例中的MyObj是MyMeta的实例,就像myobj是MyObj的实例一样。
  2. 数据描述符的优先级:当访问一个对象的属性时,Python会优先查找该对象所属类(及MRO链)中的数据描述符(拥有__set__或__delete__方法的描述符),优先级高于对象自身__dict__中的同名属性。

对应示例的行为解释

针对你的代码示例:

  • 访问MyObj.myattr时,MyObj是MyMeta的实例,Python会先检查MyMeta(即MyObj的所属类)中是否有同名数据描述符。由于MyMeta的myattr是数据描述符,直接触发它的__get__/__set__/__delete__方法,完全不会读取MyObj自身定义的myattr。
  • 访问myobj.myattr时,myobj是MyObj的实例,Python会优先检查MyObj(即myobj的所属类)中的数据描述符,也就是MyObj定义的myattr,因此触发该描述符的方法。

代码示例

class ExampleDescriptor:
    def __init__(self, name, getter_result):
        self.name = name
        self.getter_result = getter_result

    def __get__(self, obj, type=None):
        print(f'"{self.name}" getter invoked.')
        return self.getter_result

    def __set__(self, obj, value):
        print(f'"{self.name}" setter invoked with value={value}.')

    def __delete__(self, obj):
        print(f'"{self.name}" deleter invoked.')


class MyMeta(type):
    myattr = ExampleDescriptor('class level', 1)


class MyObj(metaclass=MyMeta):
    myattr = ExampleDescriptor('instance level', 2)


print(MyObj.myattr)
MyObj.myattr = 3
del MyObj.myattr

myobj = MyObj()
print(myobj.myattr)
myobj.myattr = 4
del myobj.myattr

示例输出

"class level" getter invoked.
1
"class level" setter invoked with value=3.
"class level" deleter invoked.
"instance level" getter invoked.
2
"instance level" setter invoked with value=4.
"instance level" deleter invoked.

文档依据

这个行为是两个基础规则的组合结果,均在Python官方数据模型文档中有明确说明:

  • 类是元类的实例:所有类(包括自定义类)都是type或其子类的实例,这是元编程的基础。
  • 描述符优先级:数据描述符的优先级高于实例自身的属性,当对象所属类存在同名数据描述符时,会直接使用该描述符。

内容的提问来源于stack exchange,提问作者Steve Jorgensen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 08:43:22