如何在typing.Generic泛型类中使用enforce_typing类型检查?
在泛型类中使用enforce_typing的解决方案
问题背景
enforce_typing的基础用法可正常实现类型校验:
from enforce_typing import enforce_types @enforce_types def bar(val : float) -> None: print(val) bar(3.14) # 通过 bar('3.14') # TypeError: 期望参数'val'类型为'<class 'float'>',实际为'<class 'str'>'
但在泛型类中使用时,会抛出TypeError: isinstance() arg 2 must be a type or tuple of types错误,示例代码如下:
from enforce_typing import enforce_types from typing import TypeVar, Generic T = TypeVar('T') class Foo(Generic[T]): @enforce_types def __init__(self, value: T) -> None: self.value = value @property def val(self) -> T: return self.value foo = Foo[float](3.14)
问题原因
Python泛型类型在运行时会被类型擦除,enforce_typing装饰器校验时会调用isinstance()检查参数类型,但泛型变量T并非具体类型对象,导致isinstance()触发错误。
解决方法
方法1:让enforce_typing忽略泛型变量校验
使用enforce_typing的ignore_typevars=True参数,让装饰器跳过对泛型类型变量的校验:
from enforce_typing import enforce_types from typing import TypeVar, Generic T = TypeVar('T') class Foo(Generic[T]): @enforce_types(ignore_typevars=True) def __init__(self, value: T) -> None: self.value = value @property @enforce_types(ignore_typevars=True) def val(self) -> T: return self.value foo = Foo[float](3.14) # 正常运行
注意:该方式会跳过泛型类型校验,若传入不符合T的类型(如Foo[float]("3.14")),不会触发报错。
方法2:手动实现运行时类型校验
若需要严格校验泛型的具体类型,可在实例化时捕获泛型绑定的具体类型,手动完成校验:
from enforce_typing import enforce_types from typing import TypeVar, Generic T = TypeVar('T') class Foo(Generic[T]): def __init__(self, value: T) -> None: # 获取当前类绑定的泛型具体类型 generic_base = self.__orig_bases__[0] target_type = generic_base.__args__[0] if not isinstance(value, target_type): raise TypeError(f"期望参数'value'类型为'{target_type}',实际为'{type(value)}'") self.value = value @property def val(self) -> T: return self.value foo = Foo[float](3.14) # 通过 foo = Foo[float]("3.14") # 抛出TypeError: 期望参数'value'类型为'<class 'float'>',实际为'<class 'str'>'
内容的提问来源于stack exchange,提问作者J'e
相关产品推荐
相关产品推荐

