当前位置: 首页 > 图灵资讯 > 行业资讯> 如何在Python中通过inspect模块在运行时反射检查类结构

如何在Python中通过inspect模块在运行时反射检查类结构

来源:图灵python
时间: 2026-09-03 16:21:10
inspect.getmembers() 返回大量内置和继承成员需要使用 predicate 过滤;结合描述符合协议,区分方法类型 isstaticmethod/isclassmethod;signature 报错时应捕获异常,并将其设置为 empty;优先考虑继承分析 getmro 而非 mro__;动态类需要回退 __dict 解析。

inspect.getmembers() 为什么要返回一堆奇怪的属性?

直接用 inspect.getmembers(MyClass) 会混入大量的内置方法(如 __dict____module__)继承链上的父亲根本看不出你定义了什么。关键不是“获得所有成员”,而是“过滤出你真正关心的东西”。

实操建议:

立即学习“Python免费学习笔记(深入);

  • predicate 参数限制类型,例如只看函数:inspect.getmembers(MyClass, predicate=inspect.isfunction)
  • 想看实例方法(含) self 使用参数) inspect.ismethod;但是注意:在类对象中,它只返回绑定到类的方法(如类的方法和静态的方法),不包括普通的实例方法——后者必须使用 inspect.isfunction 配合 not inspect.isbuiltin 排除掉 C 实现的函数
  • 过滤掉私人成员(双下划线开头但不结束):lambda m: not m[0].startswith('_')
如何区分 @staticmethod、@classmethod 和普通的实例方法?

仅靠 inspect.isfunctioninspect.ismethod 由于装饰改变了对象类型,因此无法准确分类。必须与之结合 inspect.signature() 判断与描述符协议。

实操建议:

立即学习“Python免费学习笔记(深入);

  • 先用 inspect.getmembers(MyClass, inspect.isfunction) 获取所有函数对象
  • 检查每个函数是否为类属性描述符:hasattr(getattr(MyClass, name), '__get__') —— 如果是这样的话,看看它是否被拒绝了。 @classmethod@staticmethod 包装
  • 更可靠的方法是检查 getattr(MyClass, name).__func__ 是否存在(@classmethod 有),或直接调用 inspect.isstaticmethod() / inspect.isclassmethod()(Python 3.12+ 只有,旧版本需要手动判断)
  • 一般实例方法 signature 第一个参数名通常是 'self',但我们不能只依赖这一点——有些函数参数被称为 'self' 却不是方法
inspect.signature() 报错 "ValueError: no signature found" 怎么办?

常见于 C 扩展函数(如 lenlist.append)、内置方法(str.upper)、或使用了 @functools.wraps 但传输不正确 __signature__ 装饰函数。

Python数据分析助手

为业务和科研数据的快速处理提供Python数据清理、统计分析和可视化建议。

下载

实操建议:

立即学习“Python免费学习笔记(深入);

  • 加 try/except 包裹:try: sig = inspect.signature(obj) except (ValueError, TypeError): sig = inspect.Signature.empty
  • 对类方法,不要直接传播 MyClass.method,而应传 MyClass.__dict__['method'](绕过绑定逻辑,获得原始函数)
  • 如果使用自定义装饰器,则确保其设置 __signature__wrapped.__signature__ = inspect.signature(func)
想看类的继承关系和 MRO,别只用 __mro__

MyClass.__mro__ 是元组,可读性差,不显示什么是显式继承,什么是通过 __bases__ 动态注入。inspect 提供更结构化的接口。

实操建议:

立即学习“Python免费学习笔记(深入)”;

  • inspect.getmro(MyClass) —— 和 __mro__ 等价,但语义更清晰
  • 对继承来源进行分析,组合使用:inspect.getfile(MyClass) 查定义位置,inspect.getsourcefile(MyClass) 判断源代码是否来(排除源代码(排除) built-in 类)
  • 检查是否为抽象基类:inspect.isabstract(MyClass),避免误把 ABC 普通类处理
  • 注意:inspect.getclasstree() 只适用于小规模集合,容易爆炸大型项目继承图。谨慎使用

最常被忽视的是:inspect 动态生成类(如使用) type() 构造、或 metaclass 修改后的)支持有限——__doc____annotations__、甚至 __signature__ 可能是空的或混乱的,这次必须回到直接阅读 __dict__ 并人工分析。