我正在开发一个接收连续数字输入流的模块。目标是检测输入数组超过某个预设阈值的第一次时间。换句话说,我需要运行一个比较函数,直到达到阈值;则该函数需要是"0";关闭;
我的想法是用decorator来解决这个问题,因为我知道它们只能有效地用于运行一个函数一次,再也不能运行了,这与我试图实现的有点相似。
在以下情况下,数字输入的连续流为: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
...
然而目前CCD_ 2在每个循环中都被调用;"关断";使用decorator的函数。
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/包装器,但一旦达到条件,就可以将其转换为no-op,这很简单,根据您的第一个注释,这似乎是您希望代码执行的操作。
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
...
这里有趣的一点是,你需要一个地方来存储状态。。。已经达到阈值的事实。我在decorator中这样做的方法是将状态附加到包装器函数。
我稍微更改了您的逻辑,这样每次调用包装器时就不会两次调用包装函数。这产生了重复的输出行,导致无法匹配您请求的输出。
简单地使用这个想法,你想要的是:"接通和断开";包装函数的调用。为此,我们可以使用父decorator函数的一个变量作为状态标志:
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