2015-02-18 41 views
0

我想在Python中编写一个装饰器来限制函数在一段时间内被调用的次数。我预计使用这样的:我如何评价Python 2.7中的函数与装饰器?

@ratelimit(seconds=15) 
def foo(): 
    print 'hello' 

start = time.time() 
while time.time() - start < 10: 
    foo() 

> 'hello' 
> 'hello' 

所以装饰功能,可以称得上是最大的每一次seconds的。在实施这方面我有这个,但我不知道正确的方式来持久last_call后续调用之间它不工作:下面

import time 

def ratelimit(seconds=10): 

    last_call = None # Never call decorated function 
    def decorator(func): 


     def wrapper(*args, **kwargs): 

      if last_call is None or time.time() - last_call > seconds: 
       result = func(*args, **kwargs) 
       last_call = time.time() 
       return result 

      return wraps(func)(wrapper) 

    return decorator 
+0

这是Python 3吗?然后使用'nonlocal'来更新一个像'last_call'这样的自由变量。 – 2015-02-18 00:46:33

+0

Python 2.7没有非本地的。 – nickponline 2015-02-18 00:53:48

+0

是的,但作为dup中的[其中一个答案](http://stackoverflow.com/a/2009474/846892)建议您可以在Python 2中使用可变项目(如列表或词典)来存储和更新这些项目。函数属性也应该起作用。 – 2015-02-18 00:57:54

回答

2

的代码在Python 2.7的工作对我罚款。

import time 
from functools import wraps 

last_called = dict() # When last called, and with what result 

def ratelimit(seconds=10, timer=time.time): 
    def decorator(func): 
     last_called[func] = None 

     @wraps(func) 
     def wrapper(*args, **kwargs): 
      now = timer() 
      call_data = last_called.get(func, None) 
      if call_data is None or now - call_data[0] >= seconds: 
       result = func(*args, **kwargs) 
       last_called[func] = (now, result) 
      else: 
       result = call_data[1] # Replay rate-limited result 
      return result 
     return wrapper 
    return decorator