Python3.8中如何基于类型注解动态校验参数类型兼容性
Python 3.8 管道步骤类型兼容性校验实现
核心实现思路
- 优先处理
Any类型:根据Python类型规则,Any和所有类型互相兼容,只要两个类型中任意一个是Any直接返回兼容 - 泛型类型拆分:用
typing.get_origin提取泛型的原始类型(如List[int]的原始类型为list),先校验原始类型是否匹配 - 泛型参数递归校验:用
typing.get_args提取泛型的参数列表,递归校验每个参数的兼容性 Union类型特殊处理:如果目标输入类型是Union,只要输出类型和Union中任意一个子类型兼容即判定为兼容
代码实现
from typing import Any, Union, get_origin, get_args, List import numpy as np def is_compatible(output_type, expected_input_type) -> bool: # 处理Any类型 if output_type is Any or expected_input_type is Any: return True # 处理Union类型(仅当目标类型是Union时判断是否匹配其中任意子类型) if get_origin(expected_input_type) is Union: return any(is_compatible(output_type, t) for t in get_args(expected_input_type)) # 提取泛型原始类型 output_origin = get_origin(output_type) or output_type expected_origin = get_origin(expected_input_type) or expected_input_type # 原始类型不兼容直接返回False if not issubclass(output_origin, expected_origin): return False # 提取泛型参数 output_args = get_args(output_type) expected_args = get_args(expected_input_type) # 参数长度不一致不兼容 if len(output_args) != len(expected_args): return False # 递归校验每个泛型参数的兼容性 for out_arg, exp_arg in zip(output_args, expected_args): if not is_compatible(out_arg, exp_arg): return False return True
测试验证
你给出的三个场景测试结果如下:
# 场景1 print(is_compatible(List, Any)) # 输出 True # 场景2 print(is_compatible(List[np.ndarray], List[Union[np.ndarray, list]])) # 输出 True # 场景3 print(is_compatible(List[str], List[int])) # 输出 False
注意事项
- 上述实现默认泛型参数为协变,符合Python标准库集合类型的默认类型规则
- 如果需要处理
Dict、Tuple等其他泛型类型,不需要修改核心逻辑,直接传入对应类型即可 - 若使用自定义泛型类,需确保自定义类的
__origin__属性可以被get_origin正确识别,或者在代码中增加自定义类型的判断分支
内容的提问来源于stack exchange,提问作者Ferus
相关产品推荐
相关产品推荐

