Python 函数注解是如何被保存的?

Python函数注解保存在__annotations__字典中,键为参数名和'return',值为注解表达式求值结果(启用PEP 563后为字符串);该字典可读写,inspect.signature()从中提取注解信息。

Python 函数注解(function annotations)被保存在函数对象的 __annotations__ 属性中,这是一个字典,键是参数名(包括返回值键 'return'),值是对应注解的原始表达式求值结果。

注解保存的位置和结构

当你为函数参数或返回值添加注解时,Python 解析器会在定义函数时将这些注解收集起来,并存入函数对象的 __annotations__ 字典。该字典在函数创建时就已存在,且只包含显式写出的注解(未标注的参数不会出现在字典中)。

  • 参数注解的键是参数名(如 'x''y'
  • 返回值注解的键固定为字符串 'return'
  • 注解表达式在函数定义时被求值(不

    是调用时),所以 intstrList[int] 等都会变成实际对象

运行时可直接访问和修改

__annotations__ 是一个普通字典,可在运行时读取、更新甚至替换,不影响函数执行逻辑(除非被类型检查工具或框架主动使用)。

  • 读取:def f(x: int) -> str: pass; print(f.__annotations__) 输出 {'x': , 'return': }
  • 修改:f.__annotations__['x'] = float 会改变该注解
  • 删除:f.__annotations__.pop('return', None) 可移除返回值注解

inspect.signature() 的关系

inspect.signature() 返回的 Signature 对象也会包含注解信息,但它是从 __annotations__ 中提取并整合进参数对象的 Parameter.annotationReturnAnnotation 中。本质上仍是同一份数据的不同封装形式。

  • 每个 Parameter.annotation 属性等于 func.__annotations__.get(参数名, Parameter.empty)
  • 返回注解通过 signature.return_annotation 暴露,等价于 func.__annotations__.get('return', Signature.empty)

PEP 563 延迟求值的影响

在 Python 3.7+ 中启用 from __future__ import annotations 后,注解不再在定义时求值,而是以字符串形式存入 __annotations__。此时字典值是原始字符串(如 "List[int]"),需用 typing.get_origin()eval()(谨慎)解析。

  • 未启用:注解是运行时对象(如 listint
  • 启用后:注解是字符串(如 "list[int]"),提升启动速度并支持前向引用
  • inspect.signature() 在启用该特性后仍能正确解析字符串注解(依赖 typing.get_type_hints()