inspect
inspect 是 Python 标准库中的自省(introspection)模块,用于在运行时获取“活对象”的详细信息。它可操作的对象包括:模块、类、方法、函数、回溯(traceback)、帧对象(frame)和代码对象(code object)。典型用途包括:类型检查(是否为类/函数/方法/生成器/协程等)、获取源码与文档字符串、格式化参数列表、获取函数签名(参数名、默认值、注解、POSITIONAL_ONLY 等)、以及检查解释器调用堆栈和当前执行帧。官方文档将上述能力归纳为四类服务:类型检查、获取源码、检查类与函数、检查解释器调用堆栈。
为何需要标准库级的自省?__doc__、dir() 等只能提供基础文档和属性名列表,难以程序化地判断“这是不是类/方法”“参数有哪些、各是什么 kind”“当前调用栈长什么样”。inspect 在标准库层面统一了这些需求,便于实现调试器、文档生成、测试框架、依赖注入等工具。其设计思路大致为:用 getmembers() 配合 is* 族函数(如 isclass、isfunction)做类型判断与成员枚举;用 getsource() / getdoc() / getfile() 等获取源码与出处;用 signature() 与 Signature / Parameter 做可调用对象的签名内省;用 stack() / currentframe() / trace() 等访问调用栈与帧,从而在需要时结合栈帧与代码对象做更底层的检查。
类型检查
getmembers() 函数获取对象如类或模块的成员。名称以 "is" 打头的函数主要用于判断对象类型。
基本类型判断
import inspect
class MyClass:
def method(self):
pass
def my_function():
pass
# 判断对象类型
print(inspect.isclass(MyClass)) # True
print(inspect.ismethod(MyClass().method)) # True
print(inspect.isfunction(my_function)) # True
print(inspect.ismodule(inspect)) # True
print(inspect.isbuiltin(print)) # True
获取对象成员
import inspect
class Person:
"""人员类"""
name = "张三"
def __init__(self, age):
self.age = age
@staticmethod
def a():
pass
@classmethod
def b(cls):
pass
def c(self):
pass
# 获取类的所有成员(属性、方法)
members = inspect.getmembers(Person)
for name, value in members:
# 排除魔法方法
if not name.startswith('__'):
print(f"{name}: {value}")
"""
a: <function Person.a at 0x00000250F315B9C0>
b: <bound method Person.b of <class '__main__.Person'>>
c: <function Person.c at 0x00000250F315BA60>
name: 张三
"""
# 只获取类方法
methods = inspect.getmembers(Person, predicate=inspect.ismethod)
print(methods)
"""
[('b', <bound method Person.b of <class '__main__.Person'>>)]
"""
# 只获取函数(包括未绑定的方法)
functions = inspect.getmembers(Person, predicate=inspect.isfunction)
print(functions)
"""
[('__init__', <function Person.__init__ at 0x000001976EF48D60>),
('a', <function Person.a at 0x000001976F0BB9C0>),
('c', <function Person.c at 0x000001976F0BBA60>)
]
"""