Python类实现装饰器的@语法底层转换及结合@classmethod、@staticmethod的实现示例
类装饰器@语法的底层转换规则
Python 对所有装饰器(无论装饰器本身是函数还是类)的@语法糖转换规则完全统一,不存在类装饰器专属的转换逻辑。
对应你给出的类装饰器示例:
class decorator_class(object): def __init__(self, original_function): self.original_function = original_function def __call__(self): print('call method before {}'.format(self.original_function.__name__)) self.original_function() @decorator_class def display(): print('display function ran...')
底层完全等价于:
display = decorator_class(display)
逻辑拆解:
- 先执行原
def display()的定义逻辑,生成原始普通函数对象,临时绑定到变量display- 调用@标记的
decorator_class(类本身是可调用对象),传入原始display函数作为唯一参数decorator_class的__init__接收该函数,生成对应的类实例- 将这个类实例重新赋值给原变量名
display
后续调用display()时,本质是触发该类实例的__call__方法,和装饰器类的设计逻辑完全匹配。
装饰器与@classmethod、@staticmethod的结合用法
@装饰器的执行顺序为从下往上逐层执行,最终的赋值逻辑是将每一层的返回值传给上一层装饰器,最终结果绑定到对应方法名。
先定义一个通用的日志装饰器,支持透传任意位置、关键字参数,方便示例复用:
def log_decorator(func): def wrapper(*args, **kwargs): print(f"[LOG] 开始执行 {func.__name__}") result = func(*args, **kwargs) print(f"[LOG] {func.__name__} 执行完成") return result return wrapper
搭配@classmethod的正确写法
class MyClass: @log_decorator @classmethod def cls_method(cls): print(f"这是类方法,当前类为 {cls.__name__}")
底层等价于:
# 1. 先定义原始的类方法函数 def cls_method(cls): print(f"这是类方法,当前类为 {cls.__name__}") # 2. 从下往上逐层执行:先把原始函数转为classmethod描述符 cls_method = classmethod(cls_method) # 3. 再把classmethod对象传给日志装饰器,得到最终的wrapper函数 cls_method = log_decorator(cls_method)
实际调用输出:
MyClass.cls_method() # 输出: # [LOG] 开始执行 cls_method # 这是类方法,当前类为 MyClass # [LOG] cls_method 执行完成
顺序说明:如果把两个装饰器的位置反过来,即
@classmethod在上、@log_decorator在下,底层会变成cls_method = classmethod(log_decorator(cls_method))。此时log_decorator接收的是未被classmethod包装的原始函数,返回的wrapper会被classmethod统一处理,虽不会报语法错误,但如果你的装饰器需要识别被装饰对象是classmethod类型的描述符,就会拿不到正确的元信息。
搭配@staticmethod的正确写法
执行逻辑与classmethod完全一致,示例:
class MyClass: @log_decorator @staticmethod def static_method(x, y): return x + y
底层等价于:
def static_method(x, y): return x + y # 先转成staticmethod描述符 static_method = staticmethod(static_method) # 再传给装饰器 static_method = log_decorator(static_method)
实际调用输出:
print(MyClass.static_method(3, 5)) # 输出: # [LOG] 开始执行 static_method # [LOG] static_method 执行完成 # 8
类装饰器与classmethod的结合示例
你之前实现的类装饰器也可以直接搭配classmethod使用,同样遵循从下往上的执行规则,示例:
class CountCallsDecorator: def __init__(self, func): self.func = func self.call_count = 0 def __call__(self, *args, **kwargs): self.call_count += 1 print(f"{self.func.__name__} 已被调用 {self.call_count} 次") return self.func(*args, **kwargs) class Demo: @CountCallsDecorator @classmethod def greet(cls): print(f"Hello from {cls.__name__}")
实际调用输出:
Demo.greet() Demo.greet() # 输出: # greet 已被调用 1 次 # Hello from Demo # greet 已被调用 2 次 # Hello from Demo
内容的提问来源于stack exchange,提问作者Parthasarathi Banerjee
相关产品推荐
相关产品推荐

