如何扩展Python中Generic类的__class_getitem__以支持更多参数?
为Python Generic类扩展__class_getitem__的正确方式
错误原因
当你使用Foo[1, bool]时,Python会把方括号内的所有内容打包成单个元组参数传给__class_getitem__,但你定义的方法要求两个独立参数,因此触发TypeError。
修正方案
让__class_getitem__接收一个元组参数,从中拆分出自定义参数和Generic需要的类型参数,再调用父类的__class_getitem__方法:
from typing import ClassVar, Generic, TypeVar T = TypeVar("T") class Foo(Generic[T]): cls_attr: ClassVar[int] def __class_getitem__(cls, params): # 拆分自定义参数与类型参数 cls_attr, item = params cls.cls_attr = cls_attr # 调用父类方法处理类型参数 return super().__class_getitem__(item) def __init__(self, arg: T): pass # 测试调用 foo = Foo[1, bool](arg=True) print(foo.cls_attr) # 输出: 1 print(type(foo)) # 输出: <class '__main__.Foo[bool]'>
注意事项
__class_getitem__的第二个参数默认接收方括号内内容组成的元组,即使只有一个元素也是元组(比如Foo[int]会传入(int,))- 直接修改原类的
ClassVar属性会影响所有实例和子类。如果需要隔离状态,建议创建动态子类来避免全局污染:
from typing import ClassVar, Generic, TypeVar T = TypeVar("T") class Foo(Generic[T]): cls_attr: ClassVar[int] def __class_getitem__(cls, params): cls_attr, item = params # 创建动态子类隔离类属性 class _FooSubclass(cls): cls_attr = cls_attr # 调用父类方法处理类型参数 return super(_FooSubclass, _FooSubclass).__class_getitem__(item) def __init__(self, arg: T): pass foo1 = Foo[1, bool](arg=True) foo2 = Foo[2, str](arg="test") print(foo1.cls_attr) # 输出: 1 print(foo2.cls_attr) # 输出: 2
内容的提问来源于stack exchange,提问作者Intrastellar Explorer
相关产品推荐
相关产品推荐

