pytransitions是一种获取触发事件历史记录的简单方法


class Matter(object):
def __init__(self, states, transitions):
self.states = states
self.transitions = transitions
self.machine = Machine(model=self, states=self.states, transitions=transitions, initial='liquid')
def get_triggered_events(self, source, dest):
self.machine.set_state(source)
eval("self.to_{}()".format(dest))
return
states=['solid', 'liquid', 'gas', 'plasma']
transitions = [
{ 'trigger': 'melt', 'source': 'solid', 'dest': 'liquid' },
{ 'trigger': 'evaporate', 'source': 'liquid', 'dest': 'gas' },
{ 'trigger': 'sublimate', 'source': 'solid', 'dest': 'gas' },
{ 'trigger': 'ionize', 'source': 'gas', 'dest': 'plasma' }

]

matter=Matter(states,transitions)
matter.get_triggered_events("solid","plasma")

我想用get_triggered_events方法获取从源到目的地的触发事件的历史记录。例如,运行matter.get_triggered_events("solid","plasma")将得到[["melt","evaporate","ionize"],["sublimate","ionize"]]。有没有一种简单的方法可以实现它?

我想您打算做的是获取从一个状态到另一个状态的所有可能路径。您对必须发出/触发才能到达目标的事件的名称感兴趣。

解决方案是遍历一个状态中可以触发的所有事件。由于一个事件可能导致多个转换,因此我们也需要在转换列表上循环。使用Machine.get_triggers(<state_name>),我们将获得可以从<state_name>触发的所有事件的列表。使用Machine.get_transitions(<event_name>, source=<state_name>),我们将获得与<event_name>相关的所有转换的列表,这些转换可以从<state_name>.触发

我们基本上将结果从Machine.get_triggers馈送到Machine.get_transitions,并在转换列表上循环,同时跟踪到目前为止已处理的事件。此外,为了防止循环遍历,我们还跟踪我们已经访问过的过渡实体:

from transitions import Machine

states = ['solid', 'liquid', 'gas', 'plasma']
transitions = [
{'trigger': 'melt', 'source': 'solid', 'dest': 'liquid'},
{'trigger': 'evaporate', 'source': 'liquid', 'dest': 'gas'},
{'trigger': 'sublimate', 'source': 'solid', 'dest': 'gas'},
{'trigger': 'ionize', 'source': 'gas', 'dest': 'plasma'}
]

class TraverseMachine(Machine):
def traverse(self, current_state, target_state, seen=None, events=None):
seen = seen or []
events = events or []
# we reached our destination and return the list of events that brought us here
if current_state == target_state:
return events
paths = [self.traverse(t.dest, target_state, seen + [t], events + [e])
for e in self.get_triggers(current_state)
for t in self.get_transitions(e, source=current_state)
if t not in seen]
# the len check is meant to prevent deep nested return values
# if you just return path the result will be:
# [[[['melt', 'evaporate', 'ionize']]], [['sublimate', 'ionize']]]
return paths[0] if len(paths) == 1 and isinstance(paths[0], list) else paths
# disable auto transitions!
# otherwise virtually every path ending with `to_<target_state>` is a valid solution
m = TraverseMachine(states=states, transitions=transitions, initial='solid', auto_transitions=False)
print(m.traverse("solid", "plasma"))
# [['melt', 'evaporate', 'ionize'], ['sublimate', 'ionize']]

您可能想看看transitions问题跟踪器中关于自动遍历的讨论,因为它包含了一些关于条件遍历的见解。

最新更新