我想构建一个通用的“ waiter”函数,该函数将接受两段输入,一遍又一遍地对其求值,直到组合表达式的值为True,然后返回第一段输入的值。但是我什至不知道这种东西叫什么,所以我很难寻找它。
我有一个执行此操作的现有函数,但我想对其进行扩展,以便将单个lambda expression
分为两部分,并返回第一部分的值。
这是我现有的代码:
def wait_until(expression, timeout=30, period=10, *args, **kwargs) -> None:
"""Wait until expression is true"""
end_time = time.time() + timeout
while time.time() < end_time:
try:
if expression(*args, **kwargs):
log.debug("That's the one!")
return
else:
log.debug("That's not the one")
except Exception as e:
log.debug(f"Exception caught and ignored while executing the predicate: {e}")
time.sleep(period)
log.error("Timed out")
raise TimeoutError(f"Timed out waiting {timeout} seconds")
我可以使用如下功能:
>>> wait_until(lambda: random.randint(0, 9) % 2 == 0)
这是我想要的新的wait_until函数的行为。我想让它返回找到后被2整除的随机数,以使用相同的示例。
我对Python还是很陌生,因此鉴于该语言提供的功能,我不知道最佳方法。我正在使用3.7,顺便说一句。
>>> from random import randint
>>> wait_until(randint(0, 9), "% 2 == 0")
4
>>> wait_until(randint(0, 9), "== 10", Timeout=30)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TimeoutError: input expression was not "== 10" in less than 30 seconds
第二个参数不必一定是字符串。要点是将第一个参数返回的值与第二个参数比较以确定真相。并且第一个参数每次都会重新评估,因为它的值预计会发生变化。
答案 0 :(得分:3)
您需要将expression
参数分成两个参数:一个函数生成值,另一个函数测试值。然后,您调用生成器,将结果传递给测试器,如果成功,则返回值。
def wait_until(generator, tester, timeout = 30, period = 10, *args, **kwargs):
end_time = time.time() + timeout
while time.time() < end_time:
try:
val = generator(*args, **kwargs)
if tester(val):
log.debug("That's the one!")
return val
else:
log.debug("That's not the one")
except Exception as e:
log.debug(f"Exception caught and ignored while executing the predicate: {e}")
time.sleep(period)
log.error("Timed out")
raise TimeoutError(f"Timed out waiting {timeout} seconds")
print(wait_until(lambda: random.randint(0, 9), lambda x: x % 2 == 0))