Python:将可选参数装饰器作为类实现
Posted
技术标签:
【中文标题】Python:将可选参数装饰器作为类实现【英文标题】:Python: Implementation of optional argument decorator as class 【发布时间】:2020-07-11 18:40:18 【问题描述】:在阅读了出色的 Primer on Python Decorators 之后,我想到了将文章中的一些花哨(高级)装饰器作为练习来实现。
例如带有参数的装饰器示例
def repeat(num_times):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
return decorator_repeat
可以实现为这样的类
class Repeat:
def __init__(self, times):
self.times = times
def __call__(self, fn):
def _wrapper(*args, **kwargs):
for _ in range(self.times):
result = fn(*args, **kwargs)
return result
return _wrapper
但是我似乎无法为optional argument decorator example 找到类解决方案:
def repeat(_func=None, *, num_times=2):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
if _func is None:
return decorator_repeat
else:
return decorator_repeat(_func)
只有我一个人,还是那个相当邪恶的人? XD 希望看到解决方案!
【问题讨论】:
【参考方案1】:刚刚遇到这个老问题,又试了一次。
我认为这是一个相当有趣的(递归)解决方案:
class Repeat:
def __init__(self, fn=None, *, times=2):
self._fn = fn
self._times = times
def _fn_proxy(self, fn):
self._fn = fn
return self
def __call__(self, *args, **kwargs):
if self._fn:
for _ in range(self._times):
result = self._fn(*args, **kwargs)
return result
# assertion: if not self._fn, then args[0] must be the decorated function object
return self._fn_proxy(args[0])
@Repeat
def fun(x,y):
print(f"x and y and fun!")
@Repeat(times=4)
def more_fun(x,y):
print(f"x and y and even more fun!")
fun(1,2)
print()
more_fun(3,4)
【讨论】:
【参考方案2】:您可以重写__new__
方法以实现相同的行为:
def __new__(cls, _func=None, *, times=2):
obj = super().__new__(cls)
obj.__init__(times)
if _func is None:
return obj
else:
return obj(_func)
这样两个:
@Repeat
def a():
print('hi')
和:
@Repeat(times=2)
def a():
print('hi')
输出:
hi
hi
【讨论】:
以上是关于Python:将可选参数装饰器作为类实现的主要内容,如果未能解决你的问题,请参考以下文章
python进阶之装饰器之2.定义一个可接受参数的装饰器如何定义一个属性可由用户修改的装饰器定义一个能接受可选参数的装饰器