状态机用于描述系统或对象在不同状态之间的转换和行为。它由一组状态(States)、一组可能的事件(Events)和一组状态转换规则(Transitions)组成。
在状态机中,系统或对象可以处于不同的状态,而事件触发状态之间的转换。每个状态可能会关联一些操作或行为,以响应特定的事件。状态机还可以定义初始状态和终止状态,表示系统或对象的起始和结束点。
github:https://github.com/pytransitions/transitions
pip install transitions==0.9.0
1. Basic
from transitions import Machine import enum class Hero: def r2a_before(self): print('r2a_before') def r2a_after(self): print('r2a_after') def a2m_before(self): print('a2m_before') def a2m_after(self): print('a2m_after') # 定义状态 class States(enum.Enum): REST = 0 ATTACK = 1 MOVE = 2 def test(): hero = Hero() machine = Machine() # 添加状态到状态机 machine.add_states(states=States, ignore_invalid_triggers=True) # 设置模型状态 machine.add_model(model=hero, initial=States.REST) # 设置状态转移 machine.add_transition(trigger='r2a', source=States.REST, dest=States.ATTACK, before='r2a_before', after='r2a_after') machine.add_transition(trigger='a2m', source=States.ATTACK, dest=States.MOVE, before='a2m_before', after='a2m_after') print('对象初始状态:', hero.state) # 进行转移状态 print('-----进行转移状态-----') hero.r2a() print('对象当前状态:', hero.state) hero.a2m() print('对象当前状态:', hero.state) print() # transitions.core.MachineError: "Can't trigger event r2a from state MOVE!" # 由于当前是 MOVE 状态, 故而 r2a 无法成功转移,抛出异常,可设置 ignore_invalid_triggers=True 避免异常 print('-----转移失败处理-----') hero.r2a() print('对象当前状态:', hero.state) print() # 检查当前状态 print('-----检查当前状态-----') print('是否 REST 状态:', hero.is_REST()) print('是否 MOVE 状态:', hero.is_MOVE()) print('是否 ATTK 状态:', hero.is_ATTACK()) print() # 无条件设置状态, 并非状态转移 print('-----强制状态设置-----') hero.to_REST() print('对象当前状态:', hero.state) if __name__ == '__main__': test()
程序执行结果:
对象初始状态: States.REST -----进行转移状态----- r2a_before r2a_after 对象当前状态: States.ATTACK a2m_before a2m_after 对象当前状态: States.MOVE -----转移失败处理----- 对象当前状态: States.MOVE -----检查当前状态----- 是否 REST 状态: False 是否 MOVE 状态: True 是否 ATTK 状态: False -----强制状态设置----- 对象当前状态: States.REST
2. Transitioning from multiple states
from transitions import Machine import enum class Hero: def rm2a_after(self): print('rm2a_after') class States(enum.Enum): REST = 0 ATTACK = 1 MOVE = 2 def test(): hero = Hero() machine = Machine() # 添加状态到状态机 machine.add_states(states=States) # 设置模型状态 machine.add_model(model=hero, initial=States.REST) # 设置状态转移 # 目标状态不支持列表 # machine.add_transition(trigger='rm2a', source=[States.REST, States.MOVE], dest=States.ATTACK) # 星号(*)表示任意状态 machine.add_transition(trigger='rm2a', source='*', dest=States.ATTACK, after='rm2a_after') print('对象初始状态:', hero.state) hero.rm2a() print('对象当前状态:', hero.state) hero.rm2a() print('对象当前状态:', hero.state) if __name__ == '__main__': test()
程序执行结果:
对象初始状态: States.REST rm2a_after 对象当前状态: States.ATTACK rm2a_after 对象当前状态: States.ATTACK
3. on_enter 和 on_exit 事件
from transitions import Machine import enum class Hero: # 针对所有状态 def on_enter_state(self): print('on_enter_state:', self.state) def on_exit_state(self): print('on_exit_state:', self.state) # 针对指定状态 def on_enter_REST_state(self): print('on_enter_REST_state:', self.state) def on_exit_REST_state(self): print('on_exit_REST_state:', self.state) def on_enter_MOVE_state(self): print('on_enter_MOVE_state:', self.state) def on_exit_MOVE_state(self): print('on_exit_MOVE_state:', self.state) class States(enum.Enum): REST = 0 ATTACK = 1 MOVE = 2 def test(): hero = Hero() machine = Machine(model=hero, initial=States.REST) machine.add_states(states=States, on_enter='on_enter_state', on_exit='on_exit_state') # 设置 REST 状态的 on_enter 事件 machine.on_enter_REST('on_enter_REST_state') machine.on_exit_REST('on_exit_REST_state') # 设置 MOVE 状态的 on_exit 事件 machine.on_enter_MOVE('on_enter_MOVE_state') machine.on_exit_MOVE('on_exit_MOVE_state') hero.to_REST() print('-' * 30) hero.to_MOVE() if __name__ == '__main__': test()
程序执行结果:
on_exit_state: REST on_exit_REST_state: REST on_enter_state: States.REST on_enter_REST_state: States.REST ------------------------------ on_exit_state: States.REST on_exit_REST_state: States.REST on_enter_state: States.MOVE on_enter_MOVE_state: States.MOVE
4. Ordered transitions
from transitions import Machine import enum class Hero: pass class States(enum.Enum): A = 0 B = 1 C = 2 def test(): hero = Hero() machine = Machine(model=hero, initial=States.A) machine.add_states(states=States) machine.add_ordered_transitions(trigger='next', loop=True) print('对象初始状态:', hero.state) for _ in range(5): hero.next() print('对象当前状态:', hero.state) if __name__ == '__main__': test()
程序执行结果:
对象初始状态: A 对象当前状态: States.B 对象当前状态: States.C 对象当前状态: States.A 对象当前状态: States.B 对象当前状态: States.C