我有以下类型的代码,但它很慢,因为report()经常被调用。
import time
import random
def report(values):
open('report.html', 'w').write(str(values))
values = []
for i in range(10000):
# some computation
r = random.random() / 100.
values.append(r)
time.sleep(r)
# report on the current status, but this should not slow things down
report(values)
Run Code Online (Sandbox Code Playgroud)
在这个说明性代码示例中,我希望报告是最新的(最多 10 年前),因此我想限制该函数。
我可以分叉报告,写入当前时间戳,然后等待该时间段,并使用共享内存时间戳检查报告是否同时被调用。如果是,则终止,如果不是,则写报告。
Python 有没有更优雅的方法?
这是一个装饰器,它将接受一个参数来保护内部函数多长时间,如果调用得太早,则会引发异常。
import time
from functools import partial, wraps
class TooSoon(Exception):
"""Can't be called so soon"""
pass
class CoolDownDecorator(object):
def __init__(self,func,interval):
self.func = func
self.interval = interval
self.last_run = 0
def __get__(self,obj,objtype=None):
if obj is None:
return self.func
return partial(self,obj)
def __call__(self,*args,**kwargs):
now = time.time()
if now - self.last_run < self.interval:
raise TooSoon("Call after {0} seconds".format(self.last_run + self.interval - now))
else:
self.last_run = now
return self.func(*args,**kwargs)
def CoolDown(interval):
def applyDecorator(func):
decorator = CoolDownDecorator(func=func,interval=interval)
return wraps(func)(decorator)
return applyDecorator
Run Code Online (Sandbox Code Playgroud)
然后:
>>> @CoolDown(10)
... def demo():
... print "demo called"
...
>>>
>>> for i in range(12):
... try:
... demo()
... except TooSoon, exc:
... print exc
... time.sleep(1)
...
demo called
Call after 8.99891519547 seconds
Call after 7.99776816368 seconds
Call after 6.99661898613 seconds
Call after 5.99548196793 seconds
Call after 4.9943420887 seconds
Call after 3.99319410324 seconds
Call after 2.99203896523 seconds
Call after 1.99091005325 seconds
Call after 0.990563154221 seconds
demo called
Call after 8.99888515472 seconds
Run Code Online (Sandbox Code Playgroud)