Python 泛型类上的类方法
我尝试在泛型类上调用classmethod: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
从输入导入列表、联合、类型变量、通用
从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'对象不可编辑
。因此TypeVarT
与EnumGender
不匹配
我怎样才能解决这个问题?预期的行为将是
>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]
是类型注释,而不是类对象。