运行 一个函数,直到它先 returns 为真,然后再不 运行 它
Run a function until it first returns True, then do not run it again
我正在开发一个接收连续数字输入流的模块。目标是检测 第一次 输入数组超过某个预设阈值的时间。换句话说,我需要运行一个比较函数,直到达到阈值为止;那么该功能需要“关闭”。
我的想法是用装饰器来解决这个问题,因为我知道装饰器可以有效地用于 运行 只用一次并且永远不会再用一个函数,这有点类似于我正在尝试的实现。
在下面的例子中,连续的数字输入流是:12, 19, 82, 92, 26, ...
。在这种情况下,预期输出将是:
Rand. val: 12
above_threshold returns False
Rand. val: 19
above_threshold returns False
Rand. val: 82
above_threshold returns True
Threshold has been reached!
Comparison function above_threshold shouldn't be called any more.
Rand. val: 92
Rand. val: 26
...
不过目前 above_threshold
在每个循环中都会被调用,我还没有成功地使用装饰器“关闭”该功能。
import time
import random
random.seed(12771)
threshold = 75
def run_until_first_true_reached(f):
"""
Decorator that runs the function f until it first returns True.
After returning True once, it will stop running the wrapped function again.
"""
def wrapper(*args, **kwargs):
# If f is False
if not f(*args, **kwargs):
return f(*args, **kwargs)
# If f is True
else:
print("Threshold has been reached!")
print("Comparison function above_threshold shouldn't be called any more.")
# tried an empty "return" in this line but didn't solve the issue
return wrapper
@run_until_first_true_reached
def above_threshold(value, threshold):
if value > threshold:
print("above_threshold returns True")
return True
else:
print("above_threshold returns False")
return False
# Modelling the continuous stream of inputs
for _ in range(100):
rand_val = random.randint(1,100)
print("Rand. val: ", rand_val)
above_threshold(rand_val, threshold)
time.sleep(1)
我不知道有什么方法可以让 decorator/wrapper 在达到条件后不被调用,但是一旦达到条件就将其变成空操作非常简单,通过您的第一条评论似乎是您希望代码执行的操作。
import time
import random
random.seed(12771)
threshold = 75
def run_until_first_true_reached(f):
"""
Decorator that runs the function f until it first returns True.
After returning True once, it will stop running the wrapped function again.
"""
def wrapper(*args, **kwargs):
if not wrapper.reached:
v = f(*args, **kwargs)
# If f is False
if not v:
return v
# If f is True
else:
print("Threshold has been reached!")
print("Comparison function above_threshold shouldn't be called any more.")
wrapper.reached = True
return None # ? or wahtever we want to return once the threshold is reached
wrapper.reached = False
return wrapper
@run_until_first_true_reached
def above_threshold(value, threshold):
if value > threshold:
print("above_threshold returns True")
return True
else:
print("above_threshold returns False")
return False
# Modelling the continuous stream of inputs
for _ in range(100):
rand_val = random.randint(1,100)
print("Rand. val: ", rand_val)
above_threshold(rand_val, threshold)
time.sleep(1)
结果:
Rand. val: 12
above_threshold returns False
Rand. val: 19
above_threshold returns False
Rand. val: 82
above_threshold returns True
Threshold has been reached!
Comparison function above_threshold shouldn't be called any more.
Rand. val: 92
Rand. val: 26
Rand. val: 18
Rand. val: 55
...
这里有趣的一点是您需要在某处存储状态...已达到阈值的事实。我在装饰器中这样做的方法是将状态附加到包装器函数。
我稍微改变了你的逻辑,这样包装函数就不会在每次包装器调用时被调用两次。这会产生重复的输出行,导致无法匹配您请求的输出。
简单地使用你想要的想法:“打开和关闭”包装函数的调用。为此,我们可以使用父装饰器函数的变量作为状态标志:
import time
import random
random.seed(12771)
threshold = 75
def run_until_first_true_reached(f):
"""
Decorator that runs the function f until it first returns True.
After returning True once, it will stop running the wrapped function again.
"""
switch_on = True
def wrapper(*args, **kwargs):
nonlocal switch_on
if switch_on:
threshold_reached = f(*args, **kwargs)
if threshold_reached:
print("Threshold has been reached!")
print("Comparison function above_threshold shouldn't be called any more.")
switch_on = False
return wrapper
@run_until_first_true_reached
def above_threshold(value, threshold):
if value > threshold:
print("above_threshold returns True")
return True
else:
print("above_threshold returns False")
return False
输出:
Rand. val: 12
above_threshold returns False
Rand. val: 19
above_threshold returns False
Rand. val: 82
above_threshold returns True
Threshold has been reached!
Comparison function above_threshold shouldn't be called any more.
Rand. val: 92
Rand. val: 26
Rand. val: 18
Rand. val: 55
我正在开发一个接收连续数字输入流的模块。目标是检测 第一次 输入数组超过某个预设阈值的时间。换句话说,我需要运行一个比较函数,直到达到阈值为止;那么该功能需要“关闭”。
我的想法是用装饰器来解决这个问题,因为我知道装饰器可以有效地用于 运行 只用一次并且永远不会再用一个函数,这有点类似于我正在尝试的实现。
在下面的例子中,连续的数字输入流是:12, 19, 82, 92, 26, ...
。在这种情况下,预期输出将是:
Rand. val: 12
above_threshold returns False
Rand. val: 19
above_threshold returns False
Rand. val: 82
above_threshold returns True
Threshold has been reached!
Comparison function above_threshold shouldn't be called any more.
Rand. val: 92
Rand. val: 26
...
不过目前 above_threshold
在每个循环中都会被调用,我还没有成功地使用装饰器“关闭”该功能。
import time
import random
random.seed(12771)
threshold = 75
def run_until_first_true_reached(f):
"""
Decorator that runs the function f until it first returns True.
After returning True once, it will stop running the wrapped function again.
"""
def wrapper(*args, **kwargs):
# If f is False
if not f(*args, **kwargs):
return f(*args, **kwargs)
# If f is True
else:
print("Threshold has been reached!")
print("Comparison function above_threshold shouldn't be called any more.")
# tried an empty "return" in this line but didn't solve the issue
return wrapper
@run_until_first_true_reached
def above_threshold(value, threshold):
if value > threshold:
print("above_threshold returns True")
return True
else:
print("above_threshold returns False")
return False
# Modelling the continuous stream of inputs
for _ in range(100):
rand_val = random.randint(1,100)
print("Rand. val: ", rand_val)
above_threshold(rand_val, threshold)
time.sleep(1)
我不知道有什么方法可以让 decorator/wrapper 在达到条件后不被调用,但是一旦达到条件就将其变成空操作非常简单,通过您的第一条评论似乎是您希望代码执行的操作。
import time
import random
random.seed(12771)
threshold = 75
def run_until_first_true_reached(f):
"""
Decorator that runs the function f until it first returns True.
After returning True once, it will stop running the wrapped function again.
"""
def wrapper(*args, **kwargs):
if not wrapper.reached:
v = f(*args, **kwargs)
# If f is False
if not v:
return v
# If f is True
else:
print("Threshold has been reached!")
print("Comparison function above_threshold shouldn't be called any more.")
wrapper.reached = True
return None # ? or wahtever we want to return once the threshold is reached
wrapper.reached = False
return wrapper
@run_until_first_true_reached
def above_threshold(value, threshold):
if value > threshold:
print("above_threshold returns True")
return True
else:
print("above_threshold returns False")
return False
# Modelling the continuous stream of inputs
for _ in range(100):
rand_val = random.randint(1,100)
print("Rand. val: ", rand_val)
above_threshold(rand_val, threshold)
time.sleep(1)
结果:
Rand. val: 12
above_threshold returns False
Rand. val: 19
above_threshold returns False
Rand. val: 82
above_threshold returns True
Threshold has been reached!
Comparison function above_threshold shouldn't be called any more.
Rand. val: 92
Rand. val: 26
Rand. val: 18
Rand. val: 55
...
这里有趣的一点是您需要在某处存储状态...已达到阈值的事实。我在装饰器中这样做的方法是将状态附加到包装器函数。
我稍微改变了你的逻辑,这样包装函数就不会在每次包装器调用时被调用两次。这会产生重复的输出行,导致无法匹配您请求的输出。
简单地使用你想要的想法:“打开和关闭”包装函数的调用。为此,我们可以使用父装饰器函数的变量作为状态标志:
import time
import random
random.seed(12771)
threshold = 75
def run_until_first_true_reached(f):
"""
Decorator that runs the function f until it first returns True.
After returning True once, it will stop running the wrapped function again.
"""
switch_on = True
def wrapper(*args, **kwargs):
nonlocal switch_on
if switch_on:
threshold_reached = f(*args, **kwargs)
if threshold_reached:
print("Threshold has been reached!")
print("Comparison function above_threshold shouldn't be called any more.")
switch_on = False
return wrapper
@run_until_first_true_reached
def above_threshold(value, threshold):
if value > threshold:
print("above_threshold returns True")
return True
else:
print("above_threshold returns False")
return False
输出:
Rand. val: 12
above_threshold returns False
Rand. val: 19
above_threshold returns False
Rand. val: 82
above_threshold returns True
Threshold has been reached!
Comparison function above_threshold shouldn't be called any more.
Rand. val: 92
Rand. val: 26
Rand. val: 18
Rand. val: 55