首页 > 解决方案 > pytransitions 中的终端/接收器状态

问题描述

例如,我正在使用带有状态机的pytransitions

from transitions import Machine
from transitions import EventData


class Matter(object):
    def __init__(self):
        transitions = [
            {'trigger': 'heat', 'source': 'solid', 'dest': 'liquid'},
            {'trigger': 'heat', 'source': 'liquid', 'dest': 'gas'},
            {'trigger': 'cool', 'source': 'gas', 'dest': 'liquid'},
            {'trigger': 'cool', 'source': 'liquid', 'dest': 'solid'}
        ]
        self.machine = Machine(
                model=self,
                states=['solid', 'liquid', 'gas'],
                transitions=transitions,
                initial='solid',
                send_event=True
        )

    def on_enter_gas(self, event: EventData):
        print(f"entering gas from {event.transition.source}")

    def on_enter_liquid(self, event: EventData):
        print(f"entering liquid from {event.transition.source}")

    def on_enter_solid(self, event: EventData):
        print(f"entering solid from {event.transition.source}")

我想添加一个状态,任何触发器都保持相同状态,不调用转换,不明确指定每个可能的触发器,也不忽略所有无效触发器(因为这非常适合调试)。

例如,我想要一个crystal可以通过触发crystalizefrom达到的状态liquid,对此任何事件都不会执行任何操作。

这可以通过图书馆实现吗?

表达这个问题的另一种方式是ignore_invalid_triggers=True只针对特定州,而不是所有州。

标签: pythontransitionstate-machinepytransitions

解决方案


与转换类似,状态也可以用字典定义:

from transitions import Machine, MachineError


class Matter(object):
    def __init__(self):
        transitions = [
            {'trigger': 'heat', 'source': 'solid', 'dest': 'liquid'},
            {'trigger': 'heat', 'source': 'liquid', 'dest': 'gas'},
            {'trigger': 'cool', 'source': 'gas', 'dest': 'liquid'},
            {'trigger': 'cool', 'source': 'liquid', 'dest': 'solid'},
            # add a transition to 'crystal' which is valid from anywhere
            {'trigger': 'crystallize', 'source': '*', 'dest': 'crystal'},
        ]
        self.machine = Machine(
                model=self,
                states=['solid', 'liquid', 'gas',
                        # initialized 'crystal' with dictionary
                        {'name': 'crystal', 'ignore_invalid_triggers': True}],
                transitions=transitions,
                initial='solid',
                send_event=True
        )


m = Matter()
assert m.is_solid()
try:
    m.cool()  # raises a machine error since cool cannot be called from 'solid'
    assert False
except MachineError:
    pass
assert m.crystallize()  # transitions to 'crystal'
assert m.is_crystal()
assert not m.heat()  # note that the transition will return 'False' since it did not happen but no exception was thrown
assert m.is_crystal()  # state machine is still in state 'crystal'

代替{'name': 'crystal', 'ignore_invalid_triggers': True}你也可以通过State(name='crystal', ignore_invalid_triggers=True)。此表格在文档的状态部分中提到:

但在某些情况下,您可能希望默默地忽略无效触发器。您可以通过设置 ignore_invalid_triggers=True 来做到这一点(在逐个州的基础上,或对所有州全局):


推荐阅读