Python 3.12:寻找不影响静态类型检查的注解类型
用类型注解添加元数据且不影响静态分析的解决方案
你要的是仅添加元数据、不改变静态类型分析结果的注解方式——直接用Annotated加Any确实会干扰类型检查(比如Pyright会把原本的Unknown转为Any),但可以通过自定义占位符类型实现需求:
1. 自定义无干扰的元数据注解类型
先定义一个空的标记类,用来占Annotated的第一个参数位置,再包装成元数据专用的类型别名:
from typing import Annotated, TypeAlias # 空标记类,仅作为占位,无任何类型意义 class _NoTypeMarker: pass # 包装成元数据注解的别名,使用时直接添加元数据即可 Metadata: TypeAlias = Annotated[_NoTypeMarker, ...] # 实际用法示例 user_id: Metadata["user_primary_key", "auto_increment"] = 1001 username: Metadata["max_length:20", "not_null"] = "john_doe"
2. 配置类型检查器适配
以Pyright为例,在项目根目录的pyrightconfig.json中添加配置,让它把_NoTypeMarker视为和无注解等价的Unknown类型:
{ "typeCheckingMode": "strict", "treatUntypedAnnotationsAs": "unknown", "customTypes": { "_NoTypeMarker": { "treatAsUnknown": true } } }
这样标注了Metadata[...]的变量,静态分析时会被当成完全无注解的变量处理,不会改变原本的Unknown状态,同时元数据完整保留。
3. 运行时读取元数据
用typing.get_type_hints即可正常读取元数据,不影响运行时逻辑:
import typing def extract_metadata(obj, var_name): type_hints = typing.get_type_hints(obj, include_extras=True) if var_name not in type_hints: return None annotated_type = type_hints[var_name] if isinstance(annotated_type, typing.Annotated): return annotated_type.__metadata__ return None # 测试读取示例 class User: user_id: Metadata["user_primary_key", "auto_increment"] = 1001 print(extract_metadata(User, "user_id")) # 输出: ('user_primary_key', 'auto_increment')
方案核心逻辑
_NoTypeMarker是空类,本身无任何类型约束,通过类型检查器配置,让它等价于无注解状态。Annotated的元数据部分完全独立,既不会被静态分析器识别为类型信息,又能在运行时正常读取。
内容的提问来源于stack exchange,提问作者nonagon
相关产品推荐
相关产品推荐

