Python状态机(transitions模块)

news2024/11/17 16:52:58

文章目录

    • 1、为什么要用状态机?
    • 2、状态机是什么?
    • 3、状态图是什么?
    • 4、transitions是什么?
      • 官网
      • 安装
      • 使用状态机必须定义的两个要素
  • 二、实战应用
    • 1、规划state、transition
      • state:状态节点的说明
      • transition:状态转移
    • 2、编写代码
      • 创建一个基础类
      • state:状态的定义
      • callbacks相关
        • 第一种:states的`on_enter`、`on_exit`
        • 第二种:给基础类增加动态方法:`on_enter_{stateName}`、`on_exit_{stateName}`
        • 第三种:transition的回调`before`属性、`after`属性
      • transition:状态转换的定义
      • 使用
    • 3、代码总结
      • 单纯绘图
      • 封装写法
      • 枚举写法
      • auto_transitions参数设置状态机
      • 获取转换逻辑,即获取transition
      • 批量定义转换规则
      • 自反转换 machine.add_transition(dest = "=")
      • 内部转换 machine.add_transition(dest=None)
      • 顺序转换
      • 队列转换

1、为什么要用状态机?

用python做一个比较复杂的小项目,需要根据不同的输入,控制摄像头采集执行不同的任务。虽然用流程方式实现了,但阅读起来费劲,还容易出错。所以就用了状态机。

2、状态机是什么?

有限状态机(Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

FSM是一种算法思想,简单而言,有限状态机由一组状态、一个初始状态、输入和根据输入及现有状态转换为下一个状态的转换函数组成。

有限状态机是有限个状态以及在这些状态之间的转移和动作等行为的数学模型,例如交通信号灯系统。

3、状态图是什么?

一般可以用状态图来对一个状态机进行精确地描述。

例如这个可乐机的状态图,这里可乐卖50美分 。

在这里插入图片描述

4、transitions是什么?

transitions是专门设计好的应用于python的一个有限状态机设计库。

当然状态机的设计可以有很多其他的方法,选用该方法其一是因为更加简单,其二是专业人士写的状态机代码相比于自己写的肯定更加完备一点。

官网

https://github.com/pytransitions/transitions

安装

$ pip3 install transitions

使用状态机必须定义的两个要素

  • state:状态节点
  • transition:状态转移。用于从一个状态节点移动到另一个状态节点

二、实战应用

以物体状态变化为例

1、规划state、transition

state:状态节点的说明

所谓状态机,最先接触的肯定是状态,因此在设计状态机之前需要先明确有哪几种状态。

大自然中物质有4种状态:固态、液态、气态、等离子态(等离子态是热的带电气体)。

所以这里我们规划了物质的4种状态,如下表

条件/当前状态固态 solid液态 liquid气态 gas等离子态 plasma
熔化 melt液态 liquid
蒸发 evaporate气态 gas
升华 sublimate气态 gas
电离 ionize等离子态 plasma

transition:状态转移

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vV8fPnDL-1673197686411)(…/pic/image-20230108094511221.png)]

固态→熔化→液态
液态→蒸发→气态
固态→升华→气态
气态→电离→等离子态

2、编写代码

创建一个继承object的类Matter的实体对象lump,然后调用transitions.Machine()将状态机绑定到这个实体对象上。

最终得到了两个东西,一个是状态机对象machine,一个是具体的实体对象lump

之后设定状态机是用machine,运行状态机是用具体的实体对象lump

创建一个基础类

先定义一个类,把它当成基础模型,Matter就是物质类,lump不好理解的话就理解成’冰’。

## 1、创建基础类
class Matter:
    pass

lump = Matter()

state:状态的定义

支持两种定义方式

方式一:状态可以是列表的形式,列表里的形式可以是类、字符串或字典:

from transitions import Machine, State

## 1、创建基础类
class Matter:
    pass

lump = Matter()


## 2、定义状态
states = [
    State(name='solid'),  # 类,<State('solid')@4472798992>
    'liquid',  # 字符串
    {'name': 'gas'},  # 字典
    "plasma"
]


## 3、将状态加入到状态机,并将状态机绑定到lump实例对象上
machine = Machine(lump, states)  # <transitions.core.Machine object at 0x10bb1a8b0>

方式二:也可以应用到transitions模块提供的State类进行初始化,再用add_states()进行添加:

from transitions import Machine, State

## 1、创建基础类
class Matter:
    pass

lump = Matter()


## 2、绑定
machine = Machine(lump)


## 3、定义状态
solid = State('solid')
liquid = State('liquid')
gas = State('gas')
plasma = State('plasma')


## 4、将状态加入到状态机上
machine.add_states([solid, liquid, gas]) # <transitions.core.Machine object at 0x10ac6df10>

callbacks相关

有三种方式:

  • 使用states的on_enteron_exit属性进行设置。
    • on_enter:进入该状态后做的事,此时状态已经转换了。
    • on_exit:即将离开某状态时做的事,此时状态未转换。
  • 给基础类增加动态方法:on_enter_{stateName}on_exit_{stateName}
  • transition的before属性、after属性
    • before: 在 属性转换方法 调用即将开始前进行回调,此时属性未转变。
    • after: 在 属性转换方法 调用即将结束前进行回调,此时属性已改变。

先后顺序(使用转换条件进行状态转换,即执行lump.melt(),实现由solid -> liquid):

  1. transition的回调before属性
  2. state=solid的回调on_exit属性
  3. 基础类动态方法的回调on_exit_solid()方法
  4. 【此时状态已改变】
  5. state=liquid的回调on_enter属性
  6. 基础类动态方法的回调on_enter_liquid()方法
  7. transition的回调after属性

第一种:states的on_enteron_exit

可以理解为“回调”或者“钩子”。

  • on_enter:进入该状态后做的事(会执行Matter类中相应名字的函数),注意此时状态已经转换了。
  • on_exit:即将离开某状态时做的事(会执行Matter类中相应名字的函数),注意此时状态未转换。
from transitions import Machine, State

## 1、创建基础类
class Matter(object):
    def say_hello(self):
        print("hello, new state!")

    def say_goodbye(self):
        print("goodbye, old state!")

lump = Matter()


## 2、定义状态,同时给某些状态设置回调
states = [
    State(name='solid', on_exit=['say_goodbye']),
    'liquid',
    {'name': 'gas', 'on_exit': ['say_goodbye']},
    {'name': 'plasma', 'on_enter': ['say_hello']}
]

## 3、绑定并将状态加入到状态机上
machine = Machine(lump, states=states)


## 4、追加设置某些状态的回调
machine.on_enter_liquid('say_hello')  # 使用'on_enter_{stateName},动态方法'的方式设置进入liquid状态时执行的回调

第二种:给基础类增加动态方法:on_enter_{stateName}on_exit_{stateName}

# 代码看不懂可以先往下看,回头再来看即可
from transitions import State, Machine

class Matter:
    def say_hello(self):
        print('hello, ' + self.state + ' state!')

    def say_goodbye(self):
        print('goodbye, ' + self.state + ' state!')

    def on_exit_solid(self):
        print('Current ' + self.state + ' state!')

    def on_enter_liquid(self):
        print('Current ' + self.state + ' state!')

    def __init__(self):
        states = [
            State(name='solid', on_enter='say_hello', on_exit='say_goodbye'),
            State(name='liquid', on_enter='say_hello', on_exit='say_goodbye'),
            State(name='gas', on_enter='say_hello', on_exit='say_goodbye'),
            State(name='plasma', on_enter='say_hello', on_exit='say_goodbye'),
        ]

        self.machine = Machine(model=self, states=states, initial=states[0])

        self.machine.add_transition(trigger='melt', source='solid', dest='liquid')
        self.machine.add_transition(trigger='evaporate', source='liquid', dest='gas')
        self.machine.add_transition(trigger='sublimate', source='solid', dest='gas')
        self.machine.add_transition(trigger='ionize', source='gas', dest='plasma')


lump = Matter()
print(lump.state)  # solid

lump.melt()
# goodbye, solid state!
# Current solid state!
# hello, liquid state!
# Current liquid state!

print(lump.state)  # liquid
print(lump.is_solid())  # Fasle
print(lump.is_liquid())  # True

第三种:transition的回调before属性、after属性

from transitions import State, Machine

class Matter:
    def say_hello(self):
        print('hello, ' + self.state + ' state!')

    def say_goodbye(self):
        print('goodbye, ' + self.state + ' state!')

    def on_exit_solid(self):
        print('exit Current ' + self.state + ' state!')

    def on_enter_liquid(self):
        print('enter Current ' + self.state + ' state!')

    def hello(self):
        print('hello after, ' + self.state + ' state!')

    def goodbye(self):
        print('goodbye before, ' + self.state + ' state!')

    def __init__(self):
        states = [
            State(name='solid', on_enter='say_hello', on_exit='say_goodbye'),
            State(name='liquid', on_enter='say_hello', on_exit='say_goodbye'),
            State(name='gas', on_enter='say_hello', on_exit='say_goodbye'),
            State(name='plasma', on_enter='say_hello', on_exit='say_goodbye'),
        ]

        self.machine = Machine(model=self, states=states, initial=states[0])

        # before: 在 属性转换方法 调用开始之前进行回调,此时属性未转变
        # after: 在 属性转换方法 调用即将结束前进行回调,此时属性已改变
        self.machine.add_transition(trigger='melt', source='solid', dest='liquid', before='goodbye', after='hello')
        self.machine.add_transition(trigger='evaporate', source='liquid', dest='gas')
        self.machine.add_transition(trigger='sublimate', source='solid', dest='gas')
        self.machine.add_transition(trigger='ionize', source='gas', dest='plasma')

lump = Matter()
print(lump.state)  # solid
lump.melt()
# goodbye before, solid state!      # transition的回调`before`属性
# goodbye, solid state!             # state=solid的回调`on_exit`属性
# exit Current solid state!         # 基础类动态方法的回调`on_exit_{stateName}`方法

# hello, liquid state!              # state=liquid的回调`on_enter`属性
# enter Current liquid state!       # 基础类动态方法的回调`on_enter_{stateName}`方法
# hello after, liquid state!        # transition的回调`after`属性

print(lump.state)  # liquid
print(lump.is_solid())  # Fasle
print(lump.is_liquid())  # True

transition:状态转换的定义

支持两种定义方式

方式一:列表的形式,状态切换的格式如下所示:

from transitions import Machine, State

## 1、创建基础类
class Matter(object):
    def say_hello(self):
        print("hello, new state!")

    def say_goodbye(self):
        print("goodbye, old state!")

lump = Matter()


## 2、定义状态,同时给某些状态设置回调
states = [
    State(name='solid', on_exit=['say_goodbye']),
    'liquid',
    {'name': 'gas', 'on_exit': ['say_goodbye']},
    State(name='plasma', on_enter=['say_hello'])
]


## 3、定义转换规则
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' },
    { 'trigger': 'any', 'source': '*', 'dest': 'solid' } # *为任意状态
]


## 4、绑定并将状态及转换规则加入到状态机上
machine = Machine(model=lump, states=states, transitions=transitions)

定义转换规则可以简化为:

transitions = [
    ['melt', 'solid', 'liquid'],
    ['evaporate', 'liquid', 'gas'],
    ['sublimate', 'solid', 'gas'],
    ['ionize', 'gas', 'plasma'],
    ['any', '*', 'solid']
]

方式二:通过add_transition函数添加转换:

from transitions import Machine, State

## 1、创建基础类
class Matter(object):
    def say_hello(self):
        print("hello, new state!")

    def say_goodbye(self):
        print("goodbye, old state!")

lump = Matter()


## 2、定义状态,同时给某些状态设置回调
states = [
    State(name='solid', on_exit=['say_goodbye']),
    'liquid',
    {'name': 'gas', 'on_exit': ['say_goodbye']},
    State(name='plasma', on_enter=['say_hello'])
]


# 3、绑定并将状态加入到状态机上,同时指定初始状态为'solid'
# 如果未指定初始状态则默认为'initial'
machine = Machine(model=lump, states=states, initial='solid')


# 4、添加转换条件
machine.add_transition('melt', source='solid', dest='liquid')
# machine.add_transition('melt', source='solid', dest='plasma') # 只有第一个匹配melt的transition有效,因为它们trigger相同,source也相同,所以即使写了此行也不会生效。
# machine.add_transition('melt', source='gas', dest='plasma') # 相同trigger时source不同的择机匹配,即melt()的source支持solid或gas,如果source都不是则抛出异常
machine.add_transition('evaporate', source='liquid', dest='gas')
machine.add_transition('sublimate', source='solid', dest='gas')
machine.add_transition('ionize', source='gas', dest='plasma')

使用

## 把 完成"状态转换的定义"后的任意代码放到此处即可

# 打印当前状态
print(lump.state)

# is_{stateName}判断当前状态是否为solid
print(lump.is_solid()) # 返回布尔值

# (非常不推荐使用,会无视设置的转换条件)强制转换到liquid状态
lump.to_liquid()

# (推荐)使用转换条件进行状态转换,如不符合设置的转换条件则会抛出异常
lump.melt()

# (也可)使用trigger方法调用melt转化,如不符合设置的转换条件则会抛出异常
lump.trigger("melt")

# 获取solid状态触发器
machine.get_triggers('solid')

3、代码总结

单纯绘图

主要用来前期理清 state、transition思路

from transitions.extensions import GraphMachine

"""
    GraphMachine依赖graphviz,需要先安装`pip3 install graphviz`
    并确保Graphviz可执行文件在您的系统上PATH
    https://github.com/xflr6/graphviz
    http://graphviz.org/
"""


class Matter:
    pass


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'}
]
machine = GraphMachine(Matter(), states=states, transitions=transitions, initial='固态 solid')
# machine = GraphMachine(lump, states=states, transitions=transitions, initial='solid', show_auto_transitions=True)  # 完整流程
graph = machine.get_graph()
graph.edge_attr['fontname'] = 'Microsoft Yahei'
graph.node_attr['fontname'] = 'Microsoft Yahei'
graph.graph_attr['fontname'] = 'Microsoft Yahei'
graph.graph_attr['dpi'] = '300'  # 设置分辨率
graph.graph_attr.pop('label')  # 删除标题
graph.draw('result.png', prog='dot')

封装写法

from transitions import Machine


class Matter:
    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'}
    ]

    def __init__(self):
        """不定型物体

        固态→熔化→液态
        液态→蒸发→气态
        固态→升华→气态
        气态→电离→等离子态
        """
        self.machine = Machine(model=self, states=Matter.states, transitions=Matter.transitions, initial='solid')


lump = Matter()
print(lump.state)  # solid
lump.melt()
print(lump.state)  # liquid

枚举写法

from enum import Enum
from transitions import Machine


class States(Enum):
    ERROR = 0
    RED = 1
    YELLOW = 2
    GREEN = 3


transitions = [
    # 注意这里有两个名为proceed的trigger,代表着匹配到哪个source就用哪个,如果都没匹配到则抛出异常
    ['proceed', States.RED, States.YELLOW],
    ['proceed', States.YELLOW, States.GREEN],
    ['error', '*', States.ERROR]
]

m = Machine(states=States, transitions=transitions, initial=States.RED)
assert m.is_RED(), "当前状态不是红色"
assert m.state is States.RED, "当前状态不是红色"
state = m.get_state(States.RED)  # <State('RED')@4436112768>
print(state.name)  # RED
m.proceed()  # RED -> YELLOW
m.proceed()  # YELLOW -> GREEN
assert m.is_GREEN(), "当前状态不是绿色"
m.error()
assert m.state is States.ERROR

auto_transitions参数设置状态机

当 True(默认值)时,每个状态都会在基本模型中自动具有关联的 to_{state}() 便利触发器。

from transitions import Machine

class Matter:
    pass

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'}
]

lump = Matter()
machine = Machine(model=lump, states=states, transitions=transitions, initial='solid')
print(lump.state)  # solid
print(machine.get_triggers('solid'))  # 获取固态的触发器(转换状态的函数)
lump.to_plasma()  # 强制转换为等离子态 (不推荐使用强制转换,这里仅测试)
print(lump.state)  # plasma
print()

lump = Matter()
machine = Machine(model=lump, states=states, transitions=transitions, initial='solid', auto_transitions=False)  # 禁止自动转换
print(lump.state)  # 初始化状态为固态solid
print(machine.get_triggers('solid'))  # 获取固态的触发器(转换状态的函数), ['melt', 'sublimate']
try:
    lump.to_plasma()  # 尝试转换为等离子态,失败
except Exception as e:
    print(e)  # 'Matter' object has no attribute 'to_plasma'
lump.melt()
print(lump.state)  # liquid

获取转换逻辑,即获取transition

from transitions import Machine

class Matter:
    pass

def get_transitions(machine, auto_transitions=False):
    """获取转换逻辑"""
    transitions = []
    for trigger, event in machine.events.items():
        if auto_transitions is False and trigger.startswith('to_'):
            continue
        for source, _transitions in event.transitions.items():
            for i in _transitions:
                transitions.append({'trigger': trigger, 'source': source, 'dest': i.dest})
    return transitions

lump = Matter()

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'}
]
machine = Machine(model=lump, states=states, transitions=transitions)
print(get_transitions(machine))
"""
[
    {'trigger': 'melt', 'source': 'solid', 'dest': 'liquid'}, 
    {'trigger': 'evaporate', 'source': 'liquid', 'dest': 'gas'}, 
    {'trigger': 'sublimate', 'source': 'solid', 'dest': 'gas'}, 
    {'trigger': 'ionize', 'source': 'gas', 'dest': 'plasma'}
]
"""

批量定义转换规则

add_transition()的参数 source 可为列表或字符串或通配符*

from transitions import Machine

class Matter:
    pass

lump = Matter()
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'}
]
machine = Machine(model=lump, states=states, transitions=transitions, auto_transitions=False)  # 禁止自动转换
machine.add_transition('transmogrify', ['solid', 'liquid', 'gas'], 'plasma')  # 批量添加不同source
machine.add_transition('to_liquid', '*', 'liquid')  # 通配符添加
print(machine.get_triggers('solid'))
print(machine.get_triggers('liquid'))
print(machine.get_triggers('gas'))
print(machine.get_triggers('plasma'))
# ['melt', 'sublimate', 'transmogrify', 'to_liquid']
# ['evaporate', 'transmogrify', 'to_liquid']
# ['ionize', 'transmogrify', 'to_liquid']
# ['to_liquid']

自反转换 machine.add_transition(dest = “=”)

自己转换为自己,注意状态转换是实际发生的,所以会调用state相关的回调on_exiton_enter

from transitions import Machine

class Matter:
    def say_hello(self):
        print("hello, new state!")

    def say_goodbye(self):
        print("goodbye, old state!")

def change_shape():
    print(1)

lump = Matter()

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'}
]

machine = Machine(model=lump, states=states, transitions=transitions, initial='solid', auto_transitions=False)  # 禁止自动转换

machine.add_transition('touch', ['liquid', 'gas', 'plasma'], '=', after=change_shape)  # 自反转换,并在转换后调用某函数
machine.on_enter_liquid('say_hello')
print(machine.get_triggers('solid'))
print(machine.get_triggers('liquid'))
print(machine.get_triggers('gas'))
print(machine.get_triggers('plasma'))
print()
# ['melt', 'sublimate']
# ['evaporate', 'touch']
# ['ionize', 'touch']
# ['touch']

print(lump.state)
lump.melt()
print(lump.state)
lump.touch()
print(lump.state)
# solid
# hello, new state!
# liquid
# hello, new state!
# 1
# liquid

内部转换 machine.add_transition(dest=None)

不同于自反转换,内部转换不会真正转换状态,意味着transition的回调beforeafter会被调用,而state相关的回调on_exiton_enter则不会被调用。

from transitions import Machine

class Matter:
    def say_hello(self):
        print("hello, new state!")

    def say_goodbye(self):
        print("goodbye, old state!")

def change_shape():
    print(1)

lump = Matter()
states = [
    {'name': 'solid'},
    {'name': 'liquid', "on_exit": ['say_goodbye']},
    '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'}
]
machine = Machine(model=lump, states=states, transitions=transitions, initial='solid', auto_transitions=False)  # 禁止自动转换
machine.add_transition('internal', ['liquid', 'gas'], None, after=change_shape)  # 自反转换,并在转换后调用某函数
machine.on_enter_liquid('say_hello')
print(machine.get_triggers('solid'))
print(machine.get_triggers('liquid'))
print(machine.get_triggers('gas'))
print(machine.get_triggers('plasma'))
print()
# ['melt', 'sublimate']
# ['evaporate', 'internal']
# ['ionize', 'internal']
# []

print(lump.state)
lump.melt()
print(lump.state)
lump.internal()  # 内部转换,不会真正转换状态,意味着transition的回调如before或after会被调用,而state相关的回调如on_exit或on_enter则不会被调用
print(lump.state)
# solid
# hello, new state!
# liquid
# 1
# liquid

顺序转换

常见的需求是转换状态按顺序转换,如给定状态 ['A', 'B', 'C'],转换状态的情况只有 A → BB → CC → A

调用 add_ordered_transitions()

import random
from transitions import Machine

class Matter:
    pass

def check():
    success = random.randint(0, 1)  # 生成一个指定范围内的整数,包含端点
    if success:
        print('转换状态')
    else:
        print('不转换状态')
    return success

def f1():
    return check()

def f2():
    return check()

def f3():
    return check()

states = ['A', 'B', 'C']
machine = Machine(states=states, initial=states[0])

machine.add_ordered_transitions()
# machine.add_ordered_transitions(['A', 'C', 'B'])  # 指定顺序
# machine.add_ordered_transitions(conditions=check)  # 为进行转换必须通过的条件,True则转换状态
# machine.add_ordered_transitions(conditions=[f1, f2, f3])  # 同上,列表里的个数与states同,一一对应
# machine.add_ordered_transitions(loop=False)  # 禁止循环

for _ in range(4):  # 转换四次
    print(machine.state)
    machine.next_state()
    # A
    # B
    # C
    # A

队列转换

队列特点是先进先出。

转换状态会马上处理事件,意味着 on_enter 会在 after 前调用。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

昆腾微冲刺创业板上市:计划募资5亿元,股权结构较为分散

撰稿|汤汤 来源|贝多财经 近日&#xff0c;北京昆腾微电子股份有限公司&#xff08;下称“昆腾微”&#xff09;在深圳证券交易所递交招股书&#xff0c;准备在创业板上市。本次冲刺上市&#xff0c;昆腾微计划募资5.07亿元&#xff0c;拟用于音频SoC芯片升级、产业化项目&am…

(5)go-micro微服务domain层开发

文章目录一 domain层介绍说明二 model层开发三 repository层开发四 service层开发五 最后一 domain层介绍说明 domain层专注于数据库数据领域开发&#xff0c;我们把数据库相关操作全部写在domain层。 model层&#xff1a;数据表字段定义与开发 repository层&#xff1a;数据…

JIMDB 大KEY治理

大KEY判定条件 单个String类型的Key大小达到20KB并且OPS高 单个String达到100KB 集合类型的Key总大小达到1MB 集合类型的Key中元素超过8000个 大KEY影响 严重影响 QPS 、TP99 等指标&#xff0c;对大Key进行的慢操作会导致后续的命令被阻塞&#xff0c;从而导致一系列慢查询。…

前端——周总结系列一

1 JS数据类型判断 typeof&#xff1a;判断JS数据类型&#xff0c;返回一个字符串类型 注&#xff1a;在 javaScript 中&#xff0c;如果二进制的前三位都为 0 的话&#xff0c;会判定为是 Object 类型。 null 的存储二进制是 000 &#xff0c;也是前三位&#xff0c;所以系统…

面试官:说说Event Loop事件循环、微任务、宏任务

前言 JS是一门单线程语言&#xff0c;单线程就意味着&#xff0c;所有的任务需要排队&#xff0c;前一个任务结束&#xff0c;才会执行下一个任务。这样所导致的问题是&#xff1a;如果JS执行的时间过长&#xff0c;这样就会造成页面的渲染不连贯&#xff0c;导致页面渲染加载…

SOLIDWORKS有哪些好用的插件丨慧德敏学

SOLIDWORKS软件本身就带有很多插件&#xff0c;比如ToolBox、motion、routing、simulation等&#xff0c;都是直接嵌入到软件内部使用的。同时由于其API接口是完全开放的&#xff0c;因此还支持第三方插件的使用&#xff0c;SW第三方插件有很多&#xff0c;常用的有比如SolidKi…

React源码解读之ReactFiber

开始之前&#xff0c;先讲一下该文章能帮你解决哪些问题&#xff1f; facebook为什么要使用重构ReactReact Fiber是什么React Fiber的核心算法 - react是如何中断重启任务的react fiber部分源码简化版 前言 该文章涉及的源码部分基于React v17.0.2 why React Fiber 浏览器…

Spring常见面试题

Spring面试问题汇总①⭐Spring是什么对AOP的理解⭐对IOC的理解⭐如何实现IOC容器SpringBoot、SpringMVC、Spring的区别⭐⭐ApplicationContext和BeanFactory的区别⭐⭐⭐SpringBean的生命周期⭐⭐解释下Spring支持的几种bean的作用域⭐⭐Spring框架中的单例bean是线程安全的吗&…

数据库视图注意事项

视图&#xff08;view&#xff09;是一种虚拟存在的表&#xff0c;其内容由查询定义 本身并不包含数据。 它是作为一个select语法查询到的结果集&#xff0c;以此为基表创建的一张虚拟表 基表 行和列数据来自由定义视图的查询所引用的表&#xff0c;并且在引用视图时动态生成 …

【ReadPaper学术交流会】结构重参数化

提出结构重参数化的论文RepVGG 重参数化已经用在了各个领域的各个方面&#xff1a;比如YOLO-V6,YOLO-V7,可以autoperform YOLO-V6和YOLO-V7的一个PP-YOLO 1 我们想要一个像VGG一样的全是3*3卷积&#xff0c;一卷到底的结构&#xff0c;这样的结构并行度高、速度快而且省显存。…

剑指offer----C语言版----第十三天

目录 1. 删除链表的节点 1.1 题目描述 1.2 Leetcode解题的思路一&#xff08;双指针&#xff09; 1.3 Leetcode解题的思路二&#xff08;单指针&#xff09; 1.4 剑指offer上的原题 1. 删除链表的节点 原题链接&#xff1a;剑指 Offer 18. 删除链表的节点 - 力扣&#xff…

【python】类型约束(类型提示的作用)

文章目录前言一、类型系统1.动态类型2.静态类型3.鸭子类型二、变量注解1.变量注解的语法2.注解鸭子类型三、复杂&#xff08;复合型&#xff09;变量的注解1.引入2.难题3. Any的妙用4.类型变量5.类型Optional总结前言 python是一种解释型强类型动态语言python3.5以前是没有类型…

【Python】基于高德地图API的坐标转换函数

【Python】基于高德地图API的坐标转换函数 API申请&#xff1a; lbs.amap.com/api/webservice/guide/api/convert/产品介绍 坐标转换是一类简单的HTTP接口&#xff0c;能够将用户输入的非高德坐标&#xff08;GPS坐标、mapbar坐标、baidu坐标&#xff09;转换成高德坐标。 …

【学习笔记之Linux】权限之目录权限与默认权限

权限概念 一件事是否允许被谁“做”&#xff0c;这就是权限。权限 用户 文件属性。   在Linux上&#xff0c;用户分为普通用户和root。root是超级管理员 ≈ 天王老子&#xff0c;只能够有一个。root的命令提示符是#&#xff1b;普通用户通过root创建&#xff0c;可以有多个…

【Android安全】Protobuf原理与解析

protobuf 简介 抓包时看到header中有这个&#xff1a; content-type: application/x-protobuf说明包的content是以protobuf格式编码的 关于protobuf的介绍&#xff0c;可以参考&#xff1a; https://techkranti.com/what-is-protobuf-explained-for-hackers/ protobuf 的背…

C++——类和对象(一)

目录 一. 面向过程和面向对象 二. 类的引入 三. 类的定义 1.结构 2.类的作用域 3.类的两种定义方式 四. 类的访问限定符及封装 1.引入 2.访问限定符 3.封装 五. 类的实例化 六. 类对象模型 七. this指针 1.this指针的引出 2.this指针的特性 一. …

JavaScript设计模式之面向对象编程

为了深入地学习 javascript &#xff0c;奔着一名标准 Web 开发人员的标准&#xff0c;想要深入了解一下面向对象的编程思想&#xff0c;提高自己模块化开发的能力&#xff0c;编写可维护、高效率、可拓展的代码&#xff0c;最近一直拜读 《JavaScript设计模式》 &#xff0c;对…

【LeetBook】二叉树

参考资料&#xff1a;LeetBook / 二叉树 前言 差不多的解题思路就是dfs能够解决&#xff0c;其次就是bfs。 主要是递归的解法。 一刷就是了解了 解题的 思路 后序再补一些二叉树的题再刷一刷 目录树的介绍树的遍历前序遍历中序遍历后序遍历层序遍历(广度优先搜索)递归解决问题“…

【FPGA】中值滤波处理BMP图片

文章目录一、中值滤波二、BMP图片格式三、功能实现1.代码设计思路2.shift IP核3.代码实现四、结果测试参考博客一、中值滤波 中值滤波法是一种非线性平滑技术&#xff0c;它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。 中值滤波是基于排序统计理论…

【GO】K8s 管理系统项目[API部分--Ingress]

K8s 管理系统项目[API部分–Ingress] 1. 接口实现 service/dataselector.go import ("sort""strings""time"appsv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1"nwv1 "k8s.io/api/networking/v1" )// Ing…