用 cls.__dict__ 结合 MRO 过滤可筛出类自身定义的方法:遍历 cls.__dict__ 中的函数、staticmethod、classmethod,再排除在父类 __dict__ 中已存在的同名属性。

如何用 dir() 快速筛出类中定义的方法(而非继承的)
dir() 本身不区分定义位置,它返回的是当前命名空间所有可访问属性名(包括从父类继承的、从 __dict__ 注入的、甚至由 __getattr__ 动态提供的)。直接对类调用 dir(MyClass),你会看到一堆内置方法(如 __init__、__str__)和父类方法(如 __subclasshook__),干扰很大。
真正想看“这个类自己写了哪些方法”,得结合 __dict__ 过滤:
- 类自身的成员(不含继承)都存在其
__dict__中,类型为function或staticmethod/classmethod的,就是定义的方法 -
dir()可作初筛(比如排除私有属性),但不能替代__dict__判断归属 - 注意:
@property的 getter 方法也会出现在__dict__中,类型是property,不是function,需单独处理
为什么 inspect.getmembers() 比 dir() 更可靠
inspect.getmembers() 默认遍历对象的 __dict__ 和 MRO 链,但它提供 predicate 参数,能精准按类型过滤。相比手动遍历 __dict__,它自动处理了描述符(如 @property、@classmethod)的解析逻辑。
关键点:
立即学习“Python免费学习笔记(深入)”;
- 用
inspect.isfunction()只能捕获普通实例方法,漏掉@classmethod(类型是classmethod)和@staticmethod(类型是staticmethod) - 更稳妥的是用
inspect.isroutine()——它涵盖function、method、builtin_function_or_method等所有可调用对象 - 若需排除从父类继承的,必须显式传入类对象本身(而非实例),并配合
inspect.getmembers(MyClass, inspect.isroutine),再用inspect.getsourcefile()或比对__qualname__所属类来进一步筛选(见下一点)
如何确认某个方法确实是该类「定义」的,而非继承或动态添加
仅靠名字或类型不够——A 类继承 B,B 定义了 foo,那么 foo 会同时出现在 A.__dict__(未重写时为空)和 dir(A) 中。要确认定义位置,核心是查源码归属:
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 对每个方法对象,调用
inspect.getsourcefile(method),如果返回None(如内置方法)或路径不匹配当前模块,大概率不是本类定义 - 更轻量的方式是检查
method.__qualname__.split(".")[0]是否等于类名——但注意:嵌套类、闭包函数会导致__qualname__不稳定,不可全信 - 最准的做法是遍历类的 MRO,逐个检查方法是否存在于某父类的
__dict__中,第一个命中处即为定义位置;本类定义的方法,在本类__dict__中存在,且不在任何前置父类__dict__中
一个实用的获取本类定义方法的函数模板
下面这个函数不依赖源码文件,只用 __dict__ 和 MRO,适合运行时分析:
import inspect
<p>def get_defined_methods(cls):</p><h1>获取所有父类(不含自身),按 MRO 顺序</h1><pre class="brush:php;toolbar:false;">mro_without_self = cls.__mro__[1:]
own_dict = cls.__dict__
methods = []
for name, obj in own_dict.items():
if not inspect.isfunction(obj) and not isinstance(obj, (staticmethod, classmethod)):
continue
# 检查是否被父类同名属性覆盖(即该 name 在任一父类 __dict__ 中存在)
defined_in_parent = any(
hasattr(parent, "__dict__") and name in parent.__dict__
for parent in mro_without_self
)
if not defined_in_parent:
methods.append(name)
return sorted(methods)
注意:@property 不在此列(它的 __dict__ 值是 property 对象,不是函数),如需包含,得额外判断 isinstance(obj, property) 并提取 fget。
真正难的不是列出名字,而是理解 Python 属性查找链和描述符协议——很多“看起来是方法”的东西,其实根本不在 __dict__ 里。

















