让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供。
如果还有疑问可以点击头像关注私信或评论。如果答案让您满意,请采纳、点赞、关注,非常感谢!
Python装饰器灵活调用方案
要实现一个既可以带参数调用也可以不带参数调用的类装饰器,有几种常见方法,元类只是其中一种。下面我将介绍几种更简洁的实现方式:
1. 使用__new__方法实现
这是最常用的解决方案,通过重写__new__方法来处理不同调用情况:
from functools import update_wrapper
import time
class Delay:
def __new__(cls, func=None, *, times=1):
if func is None:
return lambda f: Delay(f, times=times)
instance = super().__new__(cls)
instance.__init__(func, times=times)
return instance
def __init__(self, func, *, times=1):
self.func = func
self.times = times
update_wrapper(self, func)
def __call__(self, *args, **kwargs):
print(f'休息{self.times}秒先')
time.sleep(self.times)
return self.func(*args, **kwargs)
2. 使用函数包装器实现
这种方法将类装饰器包装在一个函数中:
from functools import update_wrapper
import time
def Delay(func=None, *, times=1):
if func is None:
return lambda f: Delay(f, times=times)
class _Delay:
def __init__(self, func, times):
self.func = func
self.times = times
update_wrapper(self, func)
def __call__(self, *args, **kwargs):
print(f'休息{self.times}秒先')
time.sleep(self.times)
return self.func(*args, **kwargs)
return _Delay(func, times)
3. 使用类方法实现
这种方法利用类方法作为工厂函数:
from functools import update_wrapper
import time
class Delay:
def __init__(self, func, *, times=1):
self.func = func
self.times = times
update_wrapper(self, func)
def __call__(self, *args, **kwargs):
print(f'休息{self.times}秒先')
time.sleep(self.times)
return self.func(*args, **kwargs)
@classmethod
def with_times(cls, times):
return lambda func: cls(func, times=times)
使用方式:
@Delay
def hi(name: str) -> None:
print(f'你好呀,{name}!')
@Delay.with_times(2)
def hello(name: str) -> None:
print(f'你好呀,{name}!')
推荐方案
第一种使用__new__的方法是最简洁和Pythonic的,它不需要额外的包装函数或类方法,保持了装饰器的直观性。这也是Python标准库中许多装饰器(如@property)采用的实现方式。
装饰器调用流程:
