如何从Python泛型类型提取类型及参数?兼容3.8+版本的实现方法
兼容Python 3.8+的泛型别名自省方案
针对dataclass自省场景,我们可以通过以下代码实现泛型别名的检查、原始类型(t_orig)和类型参数(t_args)的提取,同时兼容Python 3.8及以上版本,支持3.8的typing.List[int]和3.9+的typing.List[int]、list[int]语法:
import sys import types from typing import _GenericAlias def is_generic_alias(cls) -> bool: """判断给定类型是否为泛型别名""" # Python 3.9+ 同时支持内置类型泛型别名(types.GenericAlias)和 typing 模块的泛型别名 if sys.version_info >= (3, 9): return isinstance(cls, (types.GenericAlias, _GenericAlias)) # Python 3.8 仅支持 typing 模块的泛型别名(_GenericAlias) else: return isinstance(cls, _GenericAlias) def get_generic_origin(cls): """获取泛型别名的原始类型(对应t_orig)""" if not is_generic_alias(cls): return None return getattr(cls, '__origin__', None) def get_generic_args(cls) -> tuple: """获取泛型别名的类型参数(对应t_args)""" if not is_generic_alias(cls): return () return getattr(cls, '__args__', ())
代码说明
is_generic_alias:根据Python版本适配判断逻辑。3.9+新增了内置类型直接泛化的语法(如list[int]),这类实例属于types.GenericAlias;而typing.List[int]在3.9+中与list[int]等价,同时保留对旧版_GenericAlias类型的兼容。get_generic_origin:提取泛型别名对应的原始容器类型,比如List[int]或list[int]的原始类型都是list。get_generic_args:提取泛型别名的类型参数元组,比如Dict[str, int]的参数为(str, int)。
测试示例
Python 3.8环境
from typing import List, Dict # 检查typing.List[int] print(is_generic_alias(List[int])) # 输出: True print(get_generic_origin(List[int])) # 输出: <class 'list'> print(get_generic_args(List[int])) # 输出: (int,) # 检查typing.Dict[str, int] print(is_generic_alias(Dict[str, int])) # 输出: True print(get_generic_origin(Dict[str, int])) # 输出: <class 'dict'> print(get_generic_args(Dict[str, int])) # 输出: (str, int) # 非泛型类型测试 print(is_generic_alias(list)) # 输出: False print(get_generic_origin(int)) # 输出: None
Python 3.9+环境
from typing import List, Dict # 兼容旧版typing模块泛型 print(is_generic_alias(List[int])) # 输出: True print(get_generic_origin(List[int])) # 输出: <class 'list'> print(get_generic_args(List[int])) # 输出: (int,) # 支持内置类型直接泛型 print(is_generic_alias(list[int])) # 输出: True print(get_generic_origin(list[int])) # 输出: <class 'list'> print(get_generic_args(list[int])) # 输出: (int,) # 字典类型测试 print(is_generic_alias(dict[str, int])) # 输出: True print(get_generic_origin(dict[str, int])) # 输出: <class 'dict'> print(get_generic_args(dict[str, int])) # 输出: (str, int)
内容的提问来源于stack exchange,提问作者hl037_
相关产品推荐
相关产品推荐

