有没有办法在Python中检测True到False的转换?

问题描述 投票:0回答:3

我使用下面的代码来检测从 False 到 True 的转换。我需要单独的代码,仅检测从 True 到 False 的更改。有没有办法用下面的当前代码来做到这一点?

test = [True, False, False, True, True, False, True, True, False, False, False, True]

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

 # simple self-test
 if __name__ == '__main__':
     vlist = test
     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("Phase transition")

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

注意:这不是我的代码。我正在使用此线程提供的代码:How to execute a function Once when boolean valuechange in python?

我无法在该帖子中发帖询问后续问题。 如有任何帮助,我们将不胜感激。

python boolean boolean-logic
3个回答
1
投票

问题就在这里

if new_value and not self.last_value:

所以第一部分是寻找 new_value 是否具有 Truthy 值。并且它正在寻找 self.last_value 是否具有 Falsey 值。当您开始相互比较两个不同的布尔值时,这会变得混乱。

第一部分实际上是查看 new_value 中是否有值。所以我们可以将它与没有进行比较。第二部分实际上是查看两个布尔值是否匹配,因此我们可以将它们相互比较。

将线更新为此,它应该适用于任一方向的转换。

if new_value is not None and new_value is not self.last_value:

编辑:

根据您的评论: 我们可以通过多种方法来跟踪相变,而无需逐一查找。

选项一:

使用一个函数来跟踪从 true 到 false 的转换以及从 false 到 true 的转换。我们可以将值传递回打印机函数。

def test(self):
    new_value = self.reader()
    if new_value is not None and new_value is not self.last_value:
        self.action(new_value) # Note here we are passing a value back

    self.last_value = new_value

现在我们只需添加打印机功能即可看到变化。

def printer(transition):
   print(f"Phase transition to: {transition}")

最终代码选项1:

test = [True, False, False, True, True, False, True, True, False, False, False, True]

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()    # initialize value

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

         self.last_value = new_value



# simple self-test
if __name__ == '__main__':
    vlist = test
    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(transition):
       print(f"Phase transition to: {transition}")

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

选项二:

如果您想要单独的代码用于从 false 到 true 以及从 true 到 false 的转换,则可以采用这种方法。

首先在 EdgeDetector 类中,我们需要修改 init,如下所示:

def __init__(self, reader, action_true, action_false): #Note the second action here
    self.reader = reader
    self.action_true = action_true
    self.action_false = action_false # We set it just like the previous one.
    self.last_value = reader()

然后我们就可以更新测试代码了。

def test(self):
    new_value = self.reader()
    if new_value is not None and new_value is not self.last_value:
        if new_value:
            self.action_true()
        else:
            self.action_false()

    self.last_value = new_value

然后我们修改打印机语句并添加第二条:

def printer_true():
    print("Phase transition to true")
    
def printer_false():
    print("Phase transition to false")

最后需要更新EdgeDetector的初始化。

test_subject = EdgeDetector(test_reader, printer_true, printer_false)

选项 2 的最终代码

test = [True, False, False, True, True, False, True, True, False, False, False, True]

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

     def __init__(self, reader, action_true, action_false):
         self.reader = reader
         self.action_true = action_true
         self.action_false = action_false
         self.last_value = reader()    # initialize value

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

         self.last_value = new_value



# simple self-test
if __name__ == '__main__':
    vlist = test
    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_true():
       print(f"Phase transition to true")

    def printer_false():
       print(f"Phase transition to false")

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

0
投票

想法:需要检测False、True模式,表达式为

~a & b
。 要对齐输入,请使用 input[1:] 和 input[:-1],因此
~input[:-1] & input[1:]

test = [True, False, False, True, True, False, True, True, False, False, False, True]

def edge_detector(inp):
    import numpy as np
    inp = np.array(inp)
    return np.arange(len(inp)-1)[~inp[:-1] & inp[1:]]

print(edge_detector(test))

0
投票

用 Pandas 做起来很容易:

import pandas as pd

df = pd.DataFrame()
df['test'] = [True, False, False, True, True, False, True, True, False, False, False, True]

going_true = df['test'].apply(int).diff() == 1
going_false = df['test'].apply(int).diff() == -1

going_true
0     False
1     False
2     False
3      True
4     False
5     False
6      True
7     False
8     False
9     False
10    False
11     True
Name: test, dtype: bool

going_false
0     False
1      True
2     False
3     False
4     False
5      True
6     False
7     False
8      True
9     False
10    False
11    False
Name: test, dtype: bool

请注意,它不会标记第一个

True
,但这可能是边缘检测所需的行为。

Numpy 也有一个 diff 函数,但它会删除一个元素,而不是在顶部放置一个

NaN
。这可能会混淆您的索引。

© www.soinside.com 2019 - 2024. All rights reserved.