有没有办法用装饰器多次调用一个函数?
这是我的代码:
def call_func(**case):
def decorator(func):
def wrapped_function(*args, **kwargs):
return func(*args, **case)
return wrapped_function
return decorator
@call_func(p=1, o=2)
@call_func(p=3, o=4)
@call_func(p=5, o=6)
def some_func(p, o):
print(p, o)
some_func()
输出是:
(5, 6)
但我想要:
(1, 2)
(3, 4)
(5, 6)
这可能吗?而且,这是 Pythonic 吗?
最佳答案
import functools
def call_func(cache={}, **case):
def decorator(func):
funcname = func.__name__
if funcname not in cache:
# save the original function
cache[funcname] = func
@functools.wraps(func)
def wrapped_function(**kwargs):
if cache[funcname] != func:
cache[funcname](**case)
func(**case)
return wrapped_function
return decorator
@call_func(p=1, o=2)
@call_func(p=3, o=4)
@call_func(p=5, o=6)
def some_func(p, o):
print(p, o)
some_func()
产量
(1, 2)
(3, 4)
(5, 6)
<小时/>
您的 call_func
装饰器已接近创建所需的函数调用链。
考虑一下:
def call_func(**case):
def decorator(func):
def wrapped_function(**kwargs):
print(case)
func(**case)
return wrapped_function
return decorator
@call_func(p=1, o=2)
@call_func(p=3, o=4)
@call_func(p=5, o=6)
def some_func(p, o):
print(p, o)
some_func()
产量
{'p': 1, 'o': 2}
{'p': 3, 'o': 4}
{'p': 5, 'o': 6}
(5, 6)
因此,wrapped_functions
显然是按正确的顺序调用的,并且具有 case
所需的值。唯一的问题是我们想要在每个阶段调用原始函数some_func
。
我们需要以某种方式让每个wrapped_function
访问原始some_func
。
我们可以通过给call_func
一个缓存来实现这一点,该缓存记录它第一次看到某个特定名称的函数的时间。这就是目的
def call_func(cache={}, **case):
def decorator(func):
funcname = func.__name__
if funcname not in cache:
# save the original function
cache[funcname] = func
关于Python装饰器多次调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28767826/