不能直接区分方法和普通属性,inspect.getmembers()需配合inspect.isfunction()等过滤;私有及特殊方法用name.startswith('__')排除;getattr可能触发副作用,推荐优先用vars(cls);ismethod在类对象上恒为False,应以isfunction为起点判断。

inspect.getmembers() 能否直接列出所有方法?
不能直接区分“方法”和“普通属性”,inspect.getmembers() 默认返回所有成员(包括私有属性、类变量、内置方法等),必须配合 inspect.isfunction() 或 inspect.ismethod() 过滤。注意:实例方法在类对象上是 function,在实例上才是 method;静态方法和类方法也属于 function 类型,需额外判断。
推荐做法是用 inspect.isfunction() + inspect.isbuiltin() 排除内置函数,再结合 getattr() 检查是否绑定到类:
import inspect <p>def get_class_methods(cls): return [ name for name, obj in inspect.getmembers(cls) if inspect.isfunction(obj) and not inspect.isbuiltin(obj) ] </p>
这个结果包含 @staticmethod 和 @classmethod,但不包含 __init__ 等特殊方法(除非显式保留)。
如何排除私有方法和特殊方法?
私有方法(如 _helper())和特殊方法(如 __str__())默认不应出现在“可用方法列表”中,除非业务明确需要。过滤逻辑要写清楚,避免误删或漏删:
- 用
name.startswith('_')排除所有以下划线开头的名称(含单下划线私有、双下划线特殊) - 若需保留单下划线私有方法(如约定为“受保护”),改用
name.startswith('__') and name.endswith('__')专筛双下划线特殊方法 - 注意:
__new__、__init__是函数类型,但属于构造逻辑,通常不纳入“可调用接口列表”
修正后的获取逻辑:
def get_public_methods(cls):
return [
name for name, obj in inspect.getmembers(cls)
if inspect.isfunction(obj)
and not inspect.isbuiltin(obj)
and not name.startswith('__')
]
为什么 getattr(cls, name) 有时会触发副作用?
某些类在定义时对属性访问做了动态处理(比如通过 __getattr__ 或描述符),直接调用 getattr(cls, name) 可能执行任意代码,甚至抛异常。而 inspect.getmembers() 内部使用的是 dir() + getattr() 组合,同样存在风险。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
安全做法是:只对已知安全的名称做检查,或改用 vars(cls) 获取类字典中的直接定义项(不含继承方法):
-
vars(cls)返回类自己的__dict__,不触发__getattr__ - 但它不包含从父类继承的方法,也不包含通过装饰器动态添加的方法(如
@property的 getter 函数) - 若需完整方法列表且类行为不可信,应先检查
cls.__dict__,再对继承链逐层用vars()合并
inspect.ismethod() 在类对象上永远返回 False
这是初学者最常踩的坑:inspect.ismethod() 判断的是“已绑定方法”,即形如 obj.method 的对象;而类对象上的 cls.method 是未绑定的 function。所以以下代码永远不进分支:
# ❌ 错误示例
for name, obj in inspect.getmembers(cls):
if inspect.ismethod(obj): # 这里永远为 False
print(name)
正确做法始终以 inspect.isfunction(obj) 为起点,再根据是否在类字典中、是否有 __func__ 属性等进一步分类。如果真需要区分实例方法/类方法/静态方法,得结合 isinstance(obj, classmethod) 或检查 obj.__func__ 是否存在。
动态获取方法列表这件事,表面简单,实际取决于你到底要什么:是“类自己定义的公开函数”,还是“实例能直接调用的所有方法”,或是“符合某种协议的可调用项”。没想清这点,代码就容易在继承、装饰、元编程场景下突然失效。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










