本文介绍如何通过 `annotated.__metadata__` 属性安全、标准地提取类型注解中携带的自定义元数据(如文档对象、验证规则等),避免字符串化陷阱,适用于生成 api 文档、运行时校验等场景。
在 Python 3.9+ 中,typing.Annotated 提供了一种标准化方式,为类型添加任意元数据(metadata),而这些元数据并非类型本身的一部分,而是作为额外信息附着在类型上。关键在于:
Annotated 类型对象暴露了 __metadata__ 属性,它是一个只读元组,包含除基础类型外的所有后续参数
——这正是访问你传入的 B(x="foo") 实例的正确入口。
以下是一个完整、可运行的示例:
⚠️ 注意事项:
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
__metadata__ 是 Annotated 类型对象的
实例属性
,仅当类型确实是 Annotated[...] 时才存在;务必先用 hasattr(..., '__metadata__') 或 isinstance(..., types.GenericAlias) + 检查 __origin__ is Annotated 做安全判断;
inspect.get_annotations(..., eval_str=True) 是获取已求值注解的推荐方式(尤其含字符串前向引用时),但需确保模块上下文可用;
不要尝试通过 str() 或 repr() 解析注解字符串——这不可靠且易受格式变更影响;
若需批量处理(如框架级文档生成),建议封装工具函数:
总结:Annotated.__metadata__ 是官方支持、稳定可靠的元
数据访问
机制,是构建类型驱动文档、校验、序列化等高级功能的基础。始终优先使用该属性而非字符串操作或 AST 解析,以保证代码健壮性与可维护性。
立即学习
“
Python免费学习笔记(深入)
”;
from typing import Annotated, get_args
from dataclasses import dataclass
import inspect
@dataclass
class B:
x: str
@dataclass
class A:
y: Annotated[str, B(x="foo"), "A descriptive tag"]
# 获取运行时解析后的注解字典(推荐使用 get_type_hints 或 inspect.get_annotations)
annotations = inspect.get_annotations(A, eval_str=True)
# 提取 Annotated 类型
annotated_type = annotations["y"]
# ✅ 正确方式:访问 __metadata__ 属性
if hasattr(annotated_type, '__metadata__'):
metadata = annotated_type.__metadata__
print("Metadata tuple:", metadata) # 输出: (B(x='foo'), 'A descriptive tag')
# 获取第一个元数据项(即你的 B 实例)
if metadata:
b_instance = metadata[0]
if isinstance(b_instance, B):
print("B.x =", b_instance.x) # 输出: B.x = foodef get_annotated_metadata(tp):
"""安全提取 Annotated 元数据,返回 None 若非 Annotated 类型"""
if hasattr(tp, '__metadata__') and hasattr(tp, '__origin__') and tp.__origin__ is Annotated:
return tp.__metadata__
return None
# 使用示例
meta = get_annotated_metadata(annotations["y"])
if meta:
for item in meta:
print("Metadata item:", item)