类装饰器不能直接套在方法上,因其作用对象是整个类而非单个方法;必须在装饰器内部遍历cls.__dict__,识别并分别处理普通函数、staticmethod和classmethod(需提取__func__再重建),且须用setattr替换而非直接修改__dict__。

类装饰器为什么不能直接套在方法上?
Python 的类装饰器作用对象是类本身,不是类里的方法。如果你写 @MyDecorator 在 class 前,它接收的是整个类对象,而不是单个方法。想“动态增强所有方法”,就得在装饰器内部遍历 cls.__dict__,识别出函数对象(function 或 staticmethod/classmethod),再逐个替换。
常见错误是直接对 cls.__dict__.values() 操作——这会失败,因为 __dict__ 是只读的 proxy;必须用 setattr(cls, name, new_func) 替换。
实操建议:
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
- 用
inspect.isfunction()判断普通实例方法,但注意@staticmethod和@classmethod返回的是描述符,需用isinstance(obj, (staticmethod, classmethod)) - 对
staticmethod和classmethod,要先取其__func__,包装后再重新构造成对应类型,否则会丢失绑定行为 - 跳过魔术方法(如
__init__、__call__),除非你明确需要干预它们
如何保留原方法签名和文档字符串?
如果只是简单用 functools.wraps 包一层,对普通函数有效;但遇到 staticmethod 或 classmethod 时,functools.wraps 无法自动处理描述符协议,会导致 help() 显示空文档、参数提示错乱。
实操建议:
- 对普通方法:用
@functools.wraps(original_func)包装后直接赋值 - 对
staticmethod:包装其original_func,再用staticmethod(wrapped_func)封装 - 对
classmethod:同样包装__func__,再用classmethod(wrapped_func) - 手动复制
__doc__、__annotations__和__module__,尤其当装饰器用于跨模块类时,__module__错了会导致 pickle 失败
装饰器执行时机:类定义完成时 vs 实例调用时?
类装饰器在类定义语句结束时立即执行(即 class MyClass: ... 执行完就调用装饰器),此时所有方法都已绑定到类,但实例还没创建。这意味着:你能修改类的结构,但无法访问实例状态;所有增强逻辑必须是无状态的,或依赖类属性/全局配置。
常见错误现象:
- 在装饰器里试图读
self.xxx—— 这时self还不存在 - 把耗时逻辑(如读配置文件、连数据库)写进装饰器主体 —— 它会在导入时就执行,而非首次调用时
- 误以为装饰后的方法能自动感知子类新增方法 —— 不会,装饰只作用于当前类定义时已存在的方法
性能开销和继承兼容性怎么控制? 每次方法调用都会多一层 wrapper 调用,如果 wrapper 里有复杂判断(比如按方法名前缀决定是否增强),可能带来可观开销。更隐蔽的问题是继承:父类被装饰后,子类未重写的方法仍走父类 wrapper;但如果子类重写了某个方法,该方法不会被自动再次装饰 —— 除非子类也加了同一装饰器。
实操建议:
- 把运行时判断逻辑尽量提到 wrapper 外部,比如用闭包预计算一个
set存需增强的方法名,在 wrapper 里只做if method_name in target_set: - 若需子类自动继承增强,考虑用元类(
__new__中统一处理),但代价是侵入性更强 - 避免在 wrapper 中做 I/O 或锁操作;日志类增强可用
logging.getLogger(__name__).debug(...),但别在这里初始化 handler
property + classmethod)、泛型方法(带 TypeVar 注解)、以及 __slots__ 类中动态生成的方法 —— 这些场景下,__dict__ 可能不包含全部可调用项,得结合 dir(cls) 和 getattr(cls, name) 配合判断。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










