python中`__annotations__` 和 `inspect` 模块区别??
__annotations__
和 inspect
模块在 Python 中都与类型注解(type annotations)有关,但它们的作用范围和使用方式有显著区别。下面我们从多个维度来详细对比这两者。
🧩 一、__annotations__
是什么?
__annotations__
是 Python 中类、函数或模块对象的一个内置属性,用于存储类型注解。它是一个字典,其中键是变量名或参数名,值是类型对象。
示例:
def func(a: int, b: str) -> bool:pass
print(func.__annotations__)
# 输出:{'a': <class 'int'>, 'b': <class 'str'>, 'return': <class 'bool'>}
对于类来说,__annotations__
只包含类级别的变量注解,不包含方法参数或返回值的注解:
class MyClass:x: inty: str = "hello"def method(self, a: float) -> bool:return True
print(MyClass.__annotations__)
# 输出:{'x': <class 'int'>, 'y': <class 'str'>}
🔍 二、inspect
模块是什么?
inspect
是 Python 标准库中的一个模块,用于动态检查对象的结构,包括类、函数、方法、模块等。它不仅可以获取类型注解,还能获取参数列表、默认值、源码、文档字符串等更丰富的信息。
常用功能:
inspect.signature()
:获取函数/方法的签名(包括参数名、默认值、类型注解等)inspect.getmembers()
:列出对象的所有成员inspect.isfunction()
/inspect.ismethod()
:判断对象是否为函数或方法inspect.getsource()
:获取源代码
示例:
import inspect
def func(a: int, b: str = "hi") -> bool:return True
sig = inspect.signature(func)
print(sig)
# 输出:(a: int, b: str = 'hi') -> bool
for param in sig.parameters.values():print(param.name, ":", param.annotation)
# 输出:
# a : <class 'int'>
# b : <class 'str'>
🆚 三、核心区别对比
项目 | __annotations__ | inspect 模块 |
---|---|---|
作用范围 | 只获取类型注解 | 可获取注解、参数、默认值、源码、文档等 |
内容丰富度 | 仅字典结构,仅包含注解 | 结构化对象,包含完整的函数/方法签名信息 |
适用对象 | 类、函数、模块 | 函数、方法、类、模块、帧对象等 |
获取方式 | 直接访问 obj.__annotations__ | 通过 inspect.signature() 等函数获取 |
能否获取默认值 | ❌ 不能 | ✅ 可以 |
能否获取参数顺序 | ❌ 不能 | ✅ 可以 |
能否获取方法签名 | ❌ 只能获取类变量注解 | ✅ 可以,包括参数名、类型、默认值、返回值 |
🧪 四、实际使用场景建议
使用 __annotations__
的场景:
- 你只需要类型注解,不关心参数顺序、默认值等。
- 代码简单,不想引入额外的模块。
- 在元类或装饰器中快速检查类变量类型。
使用 inspect
的场景:
- 你需要完整的函数/方法签名,包括参数名、顺序、默认值、类型注解等。
- 需要动态生成文档、进行参数校验、实现依赖注入等高级功能。
- 需要分析对象结构,如列出所有方法、属性等。
✅ 五、总结
对比项 | 推荐使用 |
---|---|
只需要类型注解 | __annotations__ |
需要完整方法签名 | inspect.signature() |
需要参数顺序/默认值 | inspect |
需要动态分析对象 | inspect |
如果你只是想查看类型注解,__annotations__ 足够轻量;但如果你需要更深入的分析(如参数顺序、默认值、方法签名等),inspect 是更强大的选择。 |