动态传递参数给函数
我需要记录每个函数被调用的次数。如果某个函数在 n
秒内被调用超过 x
次,我的程序就需要暂停,然后重置这个函数的调用次数。
我的函数调用可能看起来像这样:
a(1)
b(1,param2=2, param3=3)
c(1,param3=3)
我想到的最好办法是用一个包装函数来跟踪所有的限制。就像这样:
def wrapper(function, function_params,x,n):
if not hasattr(wrapper, "function_dict"):
wrapper.function_dict = {}
if function not in wrapper.function_dict.keys():
wrapper.function_dict[function] = {
remaining = x, expires = time.time() + n
}
remaining = wrapper.function_dict[function]['remaining']
expires = wrapper.function_dict[function]['expires']
if remaining == 0:
time.sleep(expires - time.time())
wrapper.function_dict[function] = {
remaining = x, expires = time.time() + n
}
results = ????? # call function, this is what I don't know how to do
wrapper.function_dict[function]['remaining'] -= 1
我想问的是,如何处理函数的参数?我不太确定怎么处理参数的数量可能不固定,而且有些参数可能是命名的。例如,函数 c
的定义可能是:
def c(param1,param2=2, param3=3):
return param1 + param2 + param3
但我可能只需要用 param1
和 param3
来调用它。
我的思路对吗?我觉得我可以用 **
操作符来实现这个,但我不知道该怎么继续。
2 个回答
0
这基本上就是装饰器的用途。
from collections import defaultdict
class counted:
calls = defaultdict(int)
def __init__(self,x,n):
self.x = x
self.n = n
def __call__(self,fn,*args,**kwargs):
results = fn(*args,**kwargs)
calls[fn.__name__] += 1
#do something with the count ...
@counted(3,9)
def functionWhatever(arg1,arg2,arg3,**kwargs):
return "55"
functionWhatever(1,2,3,something=5)
4
写一个装饰器,并使用星号操作符来处理任意数量的参数。
举个例子:
def pause_wrapper(x, n):
def decorator(f):
config = [x, time.time()+n]
def wrapped(*args, **kwargs):
if config[0] == 0:
time.sleep(config[1] - time.time())
config = [x, time.time() + n]
return f(*args, **kwargs)
return wrapped
return decorator
以及使用方法:
@pause_wrapper(x, n)
def function(a, b, c):
...
*args
和**kwargs
通常被称为“星号”参数。一个接受*args, **kwargs
的函数,会把所有的位置参数放到一个叫args
的元组里,把所有的关键字参数放到一个叫kwargs
的字典里。(你可以在这些星号参数之外再加其他参数,这样的话,星号参数就会接收所有没有被命名的参数)。
传递*args
和**kwargs
的效果正好相反,它们会把args
里的内容作为额外的位置参数传递,而kwargs
里的内容作为关键字参数传递。
同时使用这两者可以让你处理任何一组参数,无论是输入还是输出,这样你就可以做到透明的包装(就像这个例子一样)。