Python3.7+将PEP604 |分隔类型注解替换为Union的正则实现问题
PEP604 | 类型注解转Union兼容方案
由于Python标准库re模块不支持正则子例程语法,且嵌套场景下无法通过单次正则完成匹配,推荐采用多层循环替换方案,从最内层无嵌套的|类型组合开始逐层替换,完美覆盖所有嵌套场景:
import re from typing import Union def pep604_to_union(type_str: str) -> str: # 匹配无嵌套方括号的|分隔类型序列,自动忽略前后空格 pattern = re.compile(r"([a-zA-Z0-9_.]+(?:\[[^\[\]]*?\])?)(?:\s*\|\s*([a-zA-Z0-9_.]+(?:\[[^\[\]]*?\])?))+") while True: match = pattern.search(type_str) if not match: break # 提取所有|分隔的类型项 full_match = match.group(0) type_items = [item.strip() for item in full_match.split("|")] # 替换为Union格式 union_str = f"Union[{','.join(type_items)}]" type_str = type_str[:match.start()] + union_str + type_str[match.end():] return type_str
效果验证
你给出的三个测试用例均可正常转换:
- 输入
str|int|bool→ 输出Union[str,int,bool] - 输入
Optional[int|tuple[str|int]]→ 输出Optional[Union[int,tuple[Union[str,int]]]] - 输入
dict[str | int, list[B | C | Optional[D]]]→ 输出dict[Union[str,int], list[Union[B,C,Optional[D]]]]
解析注意事项
替换完成后调用typing.get_type_hints解析注解时,需要在传入的命名空间中声明Union,示例:
from typing import get_type_hints, Optional, dict, list, tuple # 假设替换后的注解已绑定到目标函数/类的__annotations__属性 hints = get_type_hints(your_target, globalns={"Union": Union, "Optional": Optional})
内容的提问来源于stack exchange,提问作者Wizard.Ritvik
相关产品推荐
相关产品推荐

