我使用下面的代码来检测从 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?
我无法在该帖子中发帖询问后续问题。 如有任何帮助,我们将不胜感激。
问题就在这里
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()
想法:需要检测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))
用 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
。这可能会混淆您的索引。