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('_')
仅靠 inspect.isfunction 或 inspect.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'却不是方法
常见于 C 扩展函数(如 len、list.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)
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__ 并人工分析。