Python 泛型类上的类方法

Python 泛型类上的类方法,python,python-3.x,generics,class-method,Python,Python 3.x,Generics,Class Method,我尝试在泛型类上调用classmethod: 从输入导入列表、联合、类型变量、通用 从enum导入IntEnum 班级性别(女): 男=1 女性=2 潜水员=3 T=TypeVar('T') 类枚举聚合(泛型[T]): 定义初始化(self,value:Union[int,str,List[T]])->无: 如果值=“”: raise VALUERROR(f'参数“value”不能为空!') 如果isinstance(值,列表): self.\u value=''.join([str(x.val

我尝试在泛型类上调用classmethod:

从输入导入列表、联合、类型变量、通用
从enum导入IntEnum
班级性别(女):
男=1
女性=2
潜水员=3
T=TypeVar('T')
类枚举聚合(泛型[T]):
定义初始化(self,value:Union[int,str,List[T]])->无:
如果值=“”:
raise VALUERROR(f'参数“value”不能为空!')
如果isinstance(值,列表):
self.\u value=''.join([str(x.value)表示x的值])
其他:
自我价值=str(价值)
定义包含(自身,项目:T)->布尔:
返回self.to_列表中的项目
@财产
def to_列表(自)->列表[T]:
为self中的字符返回[T(int(character))。\u值]
@财产
def值(自身)->str:
返回自我值
@类方法
def all(cls)->str:
返回“”。join([str(x.value)表示T中的x])
Genders=枚举聚合[性别]
但如果我打电话

Genders.all()
我得到错误
TypeError:'TypeVar'对象不可编辑
。因此TypeVar
T
与Enum
Gender
不匹配

我怎样才能解决这个问题?预期的行为将是

>Genders.all()
'123'

有什么想法吗?或者这是不可能的?

Python的类型提示系统用于静态类型检查器来验证代码,而
T
只是类型系统的占位符,就像模板语言中的插槽一样。它不能用作对特定类型的间接引用

如果要生成具体的实现,需要对泛型类型进行子类化。因为
Gender
是一个类而不是一个实例,所以您需要告诉类型系统您计划在什么地方使用
type[T]

因为您还希望能够将
T
用作
Enum()
(使用
EnumSubclass(int(character))
调用它),所以我还需要绑定typevar;这样,类型检查器将理解
type[T]
的所有具体形式都是可调用的,并将生成单个
T
实例,但这些
T
实例将始终具有
属性

class Gender(IntEnum):
    MALE = 1
    FEMALE = 2
    DIVERS = 3


class Genders(EnumAggregate[Gender]):
    enum = Gender
输入import ClassVar、List、Union、Type、TypeVar、Generic
从enum导入IntEnum
T=TypeVar('T',bound=IntEnum)#仅IntEnum子类
类枚举聚合(泛型[T]):
#具体实现可以在类本身*上引用'enum`*,
#这将是一个IntEnum子类。
枚举:ClassVar[类型[T]]
定义初始化(self,value:Union[int,str,List[T]])->无:
如果不是值:
raise VALUERROR('参数“value”不能为空!')
如果isinstance(值,列表):
self.\u value=''.join([str(x.value)表示x的值])
其他:
自我价值=str(价值)
定义包含(自身,项目:T)->布尔:
返回self.to_列表中的项目
@财产
def to_列表(自)->列表[T]:
#具体实现需要在此处使用self.enum
为self.\u值中的字符返回[self.enum(int(character))]
@财产
def值(自身)->str:
返回自我值
@类方法
def all(cls)->str:
#具体实现需要在此处引用cls.enum
返回“”。加入([str(x.value)用于cls.enum中的x])
使用上面的泛型类,您现在可以创建一个具体的实现,使用安装在
T
槽中的
Gender
IntEnum
作为类属性:

class Gender(IntEnum):
    MALE = 1
    FEMALE = 2
    DIVERS = 3


class Genders(EnumAggregate[Gender]):
    enum = Gender
为了能够访问
IntEnum
子类作为类属性,我们需要使用;否则,类型检查器必须假定该属性仅在实例上可用

因为
Gender
IntEnum
子类本身就是一个类,所以我们也需要告诉类型检查器这一点,因此使用


现在
Gender
具体的子类工作了;使用
EnumAggregate[Gender]
作为基类,告诉类型检查器用
T
替换
Gender
,并且由于实现使用
enum=Gender
,类型检查器看到这确实得到了正确的满足,并且代码通过了所有检查:

$bin/mypy so65064844.py
成功:在1个源文件中未找到任何问题
您可以调用
Genders.all()
生成一个字符串:

>Genders.all()
'123'

请注意,我不会将枚举值存储为字符串,而是存储为整数。在这里来回转换它几乎没有什么价值,您将自己限制为值介于0和9(单个数字)之间的枚举。

EnumAggregate[Gender]
是类型注释,而不是类对象。