我需要在超时之前检查特定条件。如果在限制之前满足条件,则返回True,否则返回False。
我正在通过以下方式
counter = 1
condition_met = False
while counter < max_limit:
if <conditions are met>:
condition_met = True
break
time.sleep(10)
counter += 1
return condition_met
我想知道是否还有一种更Python化的方式来做同样的事情。
提前感谢您的反馈
答案 0 :(得分:2)
如果不是time.sleep
,则您的循环将等效于
for _ in range(max_limit):
if <condition>:
return True
# time.sleep(10)
return False
相当于return any(<condition> for _ in range(max_limit)
。
因此,您可以({)}使用any
和or
来检查条件是否满足特定的次数,同时在每次检查之前稍作等待:
any(time.sleep(10) or <condition> for _ in range(max_limit))
这将首先评估time.sleep
,并返回None
,然后评估条件,直到满足条件或range
用完为止。
唯一的警告是,即使在第一次检查条件之前,它也会调用time.sleep
。要解决此问题,您可以先检查计数器变量,仅在该变量为> 0
时调用time.sleep
:
any(i and time.sleep(10) or <condition> for i in range(10))
是否要比长循环更明确?
按照建议的in comments,实际上您可以将上面的any
子句转换为
any(<condition> or time.sleep(10) for _ in range(max_limit))
这将首先检查条件,并且只有条件为假时,sleep
才会进行检查。比上面两个方法中的任何一个都更自然地准备好了。
答案 1 :(得分:2)
计时的一种非常好的方法是使用- shock -time
模块:
import time
def foo():
max_limit = 25 # Seconds.
start = time.time()
condition_met = False
while time.time() - start < max_limit:
if <conditions are met>:
condition_met = True
break
time.sleep(10)
return condition_met
看到了吗?该模块不仅仅可以sleep
来实现。 ;¬)
答案 2 :(得分:1)
我假设您在函数中有代码。
以下代码摆脱了变量condition_met
和break
语句。
counter = 1
# condition_met = False
while counter < max_limit:
if <conditions are met>:
# condition_met = True
return True # get rid of break statement
time.sleep(10)
counter += 1
return False
答案 3 :(得分:0)
这是另一种方法,它结合使用 threading.Timer
和函数装饰器来了解何时超过给定的时间限制。
我将@Aaron Hall 的 answer 中的方法改编为一个非常相似的 Timeout on a function call 问题,因此可以在不杀死进程中的主线程(即调用者)的情况下使用它。
在此方案中,创建一个 Timer
对象以在经过 quit
秒后调用 time_limit
函数。如果发生这种情况,quit
函数会打印出一条通知消息,然后通过调用 _thread.interrupt_main()
引发 KeyboardInterrupt
异常。包裹在原始函数周围的 decorator()
函数捕获了这个异常,并使得该函数看起来好像返回了 False
— 相反,如果没有发生这种情况,它会取消 Timer
线程并返回 { {1}}。
True
在指定时间内满足条件时打印:
from random import randint
import sys
import time
import threading
import _thread as thread # Low-level threading API
def interupt_after(time_limit):
''' Decorator to raise KeyboardInterrupt if function takes more than
`time_limit` seconds to execute.
'''
def quit_func(func_name):
print('{0}() took too long'.format(func_name), file=sys.stderr)
sys.stderr.flush()
thread.interrupt_main() # Raises KeyboardInterrupt.
def decorator(func):
def decorated(*args, **kwargs):
timer = threading.Timer(time_limit, quit_func, args=[func.__name__])
timer.start()
try:
func(*args, **kwargs) # Note return value ignored.
except KeyboardInterrupt:
return False
finally:
timer.cancel()
return True
return decorated
return decorator
if __name__ == '__main__':
@interupt_after(5)
def foo(lo, hi):
mid = (lo+hi) // 2
condition_met = False
while not condition_met:
if randint(lo, hi) == mid: # Condition to meet.
condition_met = True
break
time.sleep(1)
return condition_met
print(f'foo(40, 44):', foo(40, 44))
print('-fini-')
如果不是这样:
foo(40, 44): True
-fini-