[英]Python decorator call function multiple times
有没有办法用装饰器多次调用函数?
这是我的代码:
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的机制来传递命名参数,以从提供的args构建字典。
#!/usr/bin/env python
''' Decorator demo
Decorate a function so it can be called multiple times
with different args specified in the decorator.
From http://stackoverflow.com/q/28767826/4014959
Written by PM 2Ring 2015.02.28
'''
from __future__ import print_function
def multicall0(argdicts):
def decorator(func):
def wrapped_function(*args, **kwargs):
for d in argdicts:
func(**d)
return wrapped_function
return decorator
dlist = [
{'p':1, 'o':2},
{'p':3, 'o':4},
{'p':5, 'o':6},
]
@multicall0(dlist)
def some_func(p, o):
print(p, o)
some_func()
# ------------------------------------
def multicall1(**kwargs):
def decorator(func):
dlist = [[(k, v) for v in kwargs[k]] for k in kwargs.keys()]
argdicts = [dict(item) for item in zip(*dlist)]
def wrapped_function(*args, **kwargs):
for d in argdicts:
func(**d)
return wrapped_function
return decorator
@multicall1(p=(10, 30, 50, 70), o=(20, 40, 60, 80))
def another_func(p, o):
print(p, o)
another_func()
产量
1 2
3 4
5 6
10 20
30 40
50 60
70 80
是Pythonic吗? 也许不吧。 :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.