我需要跟踪调用集合中每个函数的次数。如果函数在x
秒内被调用超过n
次,我的程序需要暂停,之后重置该函数的计数。
我的函数调用可能如下所示:
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
来调用它。
我有正确的一般方法吗?这感觉就像我可以通过**
运算符完成的事情,但我仍然坚持如何继续进行。
答案 0 :(得分:4)
编写装饰器,并使用 splat 运算符处理任意参数。
示例:
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
被非正式地称为“splat”参数。采用*args, **kwargs
的函数接收元组args
中的所有位置参数以及字典kwargs
中的所有关键字参数。 (除了splats之外你还可以有其他参数,在这种情况下,splats会吸收所有未发送给命名参数的参数。)
传递*args
和**kwargs
会产生相反的效果,将args
的内容作为额外的位置参数传递,将kwargs
作为关键字参数传递。
使用两者允许您处理任何一组参数,允许您进行透明包装(如此示例)。
答案 1 :(得分: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)