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

时间:2017-04-07 07:22:24

标签: python boolean monitoring onchange

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

这是输出的样子:

False
False
False
False
True
True
False
False
False

所以我希望能够做的是监视这个值并执行一个简单的函数,每次布尔值从False变为True时只执行一次。我见过其他语言有一个简单的变化"功能,所以我知道它可能,并且可能比我做得更容易。

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

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

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

感谢任何帮助过的人!

编辑:

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

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()

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

3 个答案:

答案 0 :(得分:2)

您的问题框架的方式并不清楚如何获得外部价值。这必须涉及存储状态信息 - 特别是最后读取的值。

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

编写以下类来接收一个函数,该函数在被调用时返回外部变量的值。这将作为参数__init__传递给班级read_signal。第二个参数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

答案 1 :(得分:1)

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

executed = false

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

但是我不知道你的整个设置,所以为它创建某种形式的事件处理可能更好,而不是一种天真的方法。

答案 2 :(得分:1)

为什么不简单地说:

#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时触发打印...等等...