状态机用于描述系统 或对象 在不同状态之间 的转换 和行为。它由一组状态(States)、一组可能的事件(Events)和一组状态转换规则(Transitions)组成。
在状态机中,系统或对象可以处于不同的状态,而事件触发状态之间的转换。每个状态可能会关联一些操作或行为,以响应特定的事件。状态机还可以定义初始状态和终止状态,表示系统或对象的起始和结束点。
github:https://github.com/pytransitions/transitions
pip install transitions==0.9.0
- Basic {#title-0} ===================
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
- Transitioning from multiple states {#title-1} ================================================
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
- on_enter 和 on_exit 事件 {#title-2} ===================================
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
- Ordered transitions {#title-3} =================================
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