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

Python类类型属性设置机制与@classproperty装饰器Setter实现问题

问题背景

自Python 3.11起,@classmethod装饰器无法再包裹@property装饰器,开发者对实现支持setter的@classproperty装饰器需求强烈,但现有讨论仅覆盖getter方法,未涉及完整的setter逻辑。

尝试的实现代码

我尝试实现了一个带setter的classproperty描述符装饰器,期望它在类类型和类实例上表现一致,代码如下:

class classproperty:
    def __init__(self, fget=None, fset=None):
        self.fget = fget
        self.fset = fset
        super().__init__()
        
    def __get__(self, instance, owner):
        return self.fget(owner)
    
    def __set__(self, instance, value):
        owner = type(instance)
        self.fset(owner, value)
        
    def setter(self, fset):
        self.fset = fset
        return self

class A():
    _x = 0

    @classproperty
    def x(cls):
        return cls._x

    @x.setter
    def x(cls, value):
        cls._x = value
遇到的问题

通过类实例赋值时,逻辑正常工作,但直接通过类赋值时,会直接覆盖classproperty对象而非调用其__set__方法:

实例赋值测试(正常)

>>> a = A()
>>> a.x     # 调用 A.__getattribute__, A.x.__get__
0
>>> a.x = 1 # 调用 A.__setattr__, A.x.__set__
>>> a.x     # 调用 A.__getattribute__, A.x.__get__ 
1
>>> a._x    # 调用 A.__getattribute__
1

类赋值测试(异常)

>>> a = A
>>> a.x     # 调用 A.x.__get__
0
>>> a.x = 1 # 未调用 __set__, __setattr__
>>> a.x     # 未调用 __get__, __getattr__, __getattribute__
1
>>> a._x    # 未调用 __get__, __getattr__, __getattribute__
0
核心疑问

这一问题源于Python中实例与类的点查找、赋值机制差异,官方文档多聚焦__get__方法的说明,对类层面的__set__行为提及较少。我想明确两个核心问题:

  1. 类类型的点查找与赋值机制具体是怎样的?
  2. 能否让类在覆盖属性前先识别并调用描述符的setter方法?

我推测property和classmethod的纯Python实现中存在解决思路,但多次尝试仍未找到可行方案。

内容的提问来源于stack exchange,提问作者Mr G

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:16:28