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

Python中__class_getitem__引发类属性可变的问题咨询

问题根源与解决方案

核心问题

你在__class_getitem__里直接修改了类本身的属性(sub_type和max_len),类属性是所有该类的实例、甚至类本身共享的全局值。每次调用List[xxx, xxx]都会覆盖这些属性,所以不管你返回类还是实例,后续访问都会拿到最后一次修改的结果。

为什么返回实例也没用

当你返回cls()时,如果你没有给实例单独设置sub_type和max_len属性,访问实例的这两个属性时,Python会自动去类上查找对应的类属性——而类属性已经被最后一次调用的List[Int,10]修改了,所以所有实例都会用最新的类属性值。

正确实现方式

方式1:动态创建子类(适合作为类型标记)

每次调用List[xxx, xxx]时,创建一个继承自原List的子类,子类拥有自己独立的类属性,不会互相干扰:

def __class_getitem__(cls, parameters):
    if not isinstance(parameters, tuple):
        parameters = (parameters,)

    if len(parameters) > 2:
        raise TypeError("Expected 2 arguments: List[sub_type, max_length]")
    
    sub_type = parameters[0] if len(parameters) >= 1 else None
    max_len = parameters[1] if len(parameters) >= 2 else None

    if max_len is not None and max_len <= 0:
        raise TypeError(f"Max Length of {max_len} is less than or equal to 0")

    # 动态生成唯一子类,每个子类有独立的类属性
    subclass_name = f"{cls.__name__}[{sub_type.__name__}, {max_len}]"
    return type(subclass_name, (cls,), {"sub_type": sub_type, "max_len": max_len})

方式2:返回带实例属性的对象(适合直接使用)

不修改类属性,而是给创建的实例单独设置属性,每个实例的属性独立:

def __class_getitem__(cls, parameters):
    if not isinstance(parameters, tuple):
        parameters = (parameters,)

    if len(parameters) > 2:
        raise TypeError("Expected 2 arguments: List[sub_type, max_length]")
    
    sub_type = parameters[0] if len(parameters) >= 1 else None
    max_len = parameters[1] if len(parameters) >= 2 else None

    if max_len is not None and max_len <= 0:
        raise TypeError(f"Max Length of {max_len} is less than or equal to 0")

    # 创建实例并设置独立的实例属性
    instance = cls()
    instance.sub_type = sub_type
    instance.max_len = max_len
    return instance

补充说明

  • 方式1常用于类型注解场景(比如PEP 484的泛型类型),每个List[Int,10]是不同的类类型。
  • 方式2适合直接创建可使用的对象,每个实例的属性互不影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 01:57:55