状态机(State Machine)

状态机用于描述系统对象不同状态之间转换行为。它由一组状态(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

未经允许不得转载:一亩三分地 » 状态机(State Machine)
评论 (0)

1 + 5 =