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

Python中使用property时Class.foo与instance.foo的行为差异

问题解析:为什么通过类访问property返回对象本身,实例访问返回实际值?

先重现你给出的两个案例代码:

案例1:使用property

class Case1:
    # 忽略property的getter和setter
    var = property(getter, setter, None, None)

案例2:使用等效方法

class Descriptor:
    def __get__(self, obj, type=None):
        return None
    def __set__(self, obj, val):
        pass
class Case2:
    var = Descriptor()

这其实是Python描述符协议的核心逻辑在起作用,咱们把这个现象拆解开说:

首先要明确:property本质上是一个实现了描述符协议的类,它属于「数据描述符」(因为同时实现了__get__和__set__方法)。而描述符的调用行为,会根据你是通过实例访问还是类访问,产生完全不同的结果:

  1. 当通过实例访问属性时:
    Python会先检查实例的__dict__里有没有这个属性,如果没有,就去类的属性中查找。如果找到的是一个描述符(实现了__get__),就会调用这个描述符的__get__方法,并且把当前实例作为第一个参数obj传入。
    对于property来说,当obj不为None时,它会调用你绑定的getter函数,返回对应属性的实际值——这就是你看到instance.var返回实际值的原因。

  2. 当通过类访问属性时:
    同样会找到类属性里的描述符,但这时候调用__get__方法时,第一个参数obj会被传入None。而property的__get__方法做了特殊处理:当obj是None时,它会直接返回property对象本身,而不是去调用getter。
    这是Python的刻意设计——目的是让你可以直接获取到描述符对象本身,而不是触发它的属性获取逻辑。

对比你案例2里的自定义Descriptor,它的__get__方法没有处理obj为None的情况,所以不管是类访问还是实例访问,都会返回None。如果给它加上类似property的逻辑:

class Descriptor:
    def __get__(self, obj, type=None):
        if obj is None:
            return self  # 类访问时返回自身
        return None
    def __set__(self, obj, val):
        pass

这时候你再访问Case2.var,就会返回Descriptor对象本身,和property的表现一致了。

总结一下核心点:

  • property的__get__方法对「类访问」和「实例访问」做了分支处理;
  • 类访问时返回自身,方便你操作描述符对象;
  • 实例访问时触发getter逻辑,返回实际属性值。

内容的提问来源于stack exchange,提问作者Sheng Wang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:13:29