如何在python中布尔值变化时执行一次函数?

How to execute a function once when boolean value changes in python?

我正在监视一个外部设备,它在不满足条件时输出布尔值 False,在满足条件时输出布尔值 True。 问题是,布尔值在满足条件后不止一次输出。

这是输出的样子:

False
False
False
False
True
True
False
False
False

所以我想做的是监视这个值并执行一个简单的函数,每次布尔值从 False 变为 True 时只执行一次。我见过其他具有简单 "on change" 功能的语言,所以我知道它是可能的,而且可能比我想象的要容易得多。

目前我有这个。为了解释这一点,变量 "ext_data" 被用作 python 脚本正在监视的外部数据。

while True:
    if ext_data == True:
        print("true")
        pass

每次布尔值等于 true 时都会打印 "true",当它自身重置时,布尔值仍设置为 True,所以当我只想要一个时我会得到多个读数。

感谢所有提供帮助的人!

编辑:

使用由 holdenweb 编写的 EdgeDetector class 更新了代码。

ext_data = True/False  # This returns True or False depending on the state
                       # of the variable. It is constantly monitored and
                       # could change at any moment, which is why I'm 
                       # running the function in a while True loop
def printer():
    print(u'something%s' % serialport.cts)
    post_to_api('cycle_count')

def myfunction():
    return ext_data

test_subject = EdgeDetector(myfunction, printer)

while True:

    test_subject.test()

这仍然是 returns 偶尔重复的帖子。有人提到,这些数据需要放在数组中,EdgeDetector Class 才能正常工作,您如何建议将这些数据放入数组而不创建无限长的数组?

你可以有一个你跟踪的内部变量(伪代码)

executed = false

if(!executed && output_from_device == true)
    print("true")
    executed = true

但我不知道您的整个设置,因此最好为它创建某种形式的事件处理而不是天真的方法。

为什么不简单一些:

#Input Boolean
inputData = [True,False,False,False,True,True,False]


foo =''

for i in inputData:
   if foo != i:
      print("Yo")
      foo = i

InputData 的第一个元素将触发打印,因为 foo 为空,然后当 foo = True 时,下一次将在 inputData 元素为 False 时触发打印...等等...

你提出问题的方式并没有说明外部价值是如何获得的。这必须涉及存储状态信息 - 特别是读取的最后一个值。

虽然可以将它存储在一个全局变量中,但这不是一个好的做法 - 虽然它可以满足您的即时需求,但如果您尝试基于它创建可重用的软件组件,它会崩溃如果同一模块中的某些其他代码决定将同一全局变量用于其他目的。所以一个class可能更令人满意。

下面的class写的是接收一个函数,调用时,returns外部变量的值。这作为参数 read_signal 传递给 class 的 __init__。第二个参数 action 是对象在检测到 FalseTrue 转换时应调用的函数。

以这种形式转换它意味着您可以轻松地将它集成到任何程序中,如果您资助自己处理许多外部变量,您可以为每个变量创建一个 EdgeDetector

class EdgeDetector:
    """Detects False to True transitions on an external signal."""

    def __init__(self, reader, action):
        self.reader = reader
        self.action = action
        self.last_value = reader()    # initialise value

    def test(self):
        new_value = self.reader()
        if new_value and not self.last_value:
            self.action()
        self.last_value = new_value

if __name__ == '__main__':                 # simple self-test
    vlist = [False, False, False, True, True, False, True, True, False, False, False, True]
    vgen = (v for v in vlist)              # generator for value sequence

    def test_reader():                     # generate test sequence
        value = next(vgen)
        print("Read:", value)
        return value

    def printer():
        print("Edge transition detected")

    test_subject = EdgeDetector(test_reader, printer)
    for i in range(len(vlist)-1):
        test_subject.test()

通常您会将该模块导入到您的程序中,以便于重复使用并使实现细节远离您的主要代码。当 运行 作为程序时,自测代码会向您显示输入值的序列以及检测到转换的时间,让您在部署代码之前对代码更有信心。自测的输出为

Read: False
Read: False
Read: False
Read: True
Edge transition detected
Read: True
Read: False
Read: True
Edge transition detected
Read: True
Read: False
Read: False
Read: False
Read: True
Edge transition detected