python状态机实现初学---transitions库

前情介绍

之前做的项目中基本都是用到了有限状态机,直到python3.10才出现了match-case语句。之前直接很暴力的if-else实现了状态机的跳转。其实对于python来说,if-else的结构无可厚非,甚至在某些情况下比复杂的判断逻辑+跳转还要省内存。但是,这样子一是不够美观,二是属性全部对外暴露,并且当你想对状态机的总数进行修改或增加跳转时,往往会产生不可预料的问题。随着表的状态的扩展,状态之间的流转也会越来越复杂。

问:那既然3.10出来了,为啥不用match-case呢
因项目需求,python环境不一定都会是3.10版本。而且目前网上都流传match-case有性能上的问题,有时甚至不如if-else方便。我也不清楚为啥,但是总之先信了呗。毕竟match-case只能对单一对象进行判断(if真好用.jpg)。

transitions库

作为专门为了python实现有限状态机的库,它肯定能够实现我们想到的功能。

安装

conda等虚拟环境自己去找

pip install transitions

实现

创建状态机对象

我们创建了两个对象:实体对象lump和状态机对象machine。
接下来操作时,设定状态机使用machine,运行状态机使用lump。

from transitions import Machine

class Matter(object):
	pass

lump = Matter()  # 创建实体对象lump
machine = Machine(model=lump)  # 创建状态机对象machine

添加状态state

创建states的方法不止下面一种。但是这种是我觉得用着最舒服和最清晰的。

states列表中每一个列表元素代表了一个状态,name属性为状态的名字,on_enter属性表示进入状态时触发的函数(列表可为多个函数,顺序触发),on_exit表示退出状态时触发的函数(同上)。
同时因为pycharm的警告,后续pycharm会认为state变量未被初始化,所以我们直接在class内部初始化定义虚假的state,运行时该值会被再次修改。

参数作用是否必选
name状态节点的名称
on_enter进入状态节点时触发的事件X
on_exit退出状态节点时触发的事件X

需要注意的是,on_enter不会在初始化时被触发。

from transitions import Machine

class Matter(object):
    def __init__(self):  # 定义虚假的state,防止看着pycharm的警告不顺心
        self.state = None

    def init(self): print("Hello, init!")
    def exit(self): print("Goodbye")

lump = Matter()  # 创建实体对象lump

states = [
    {'name': "00", 'on_enter': ['init']},
    {'name': "01"},
    {'name': "02"},
    {'name': "09", 'on_enter': ['exit']},
    {'name': "ERROR"},
]  # 定义状态机的state
machine = Machine(model=lump, states=states, initial=states[0]['name'])  # 创建状态机对象machine

添加状态机transition

还是一样,用自己觉得最舒服的添加方式。

参数作用是否必选
triggertransition的名称
source原状态节点
dest目标状态节点

若transition名称重复,则只有第一条生效。

from transitions import Machine

class Matter(object):
    def __init__(self):  # 定义虚假的state,防止看着pycharm的警告不顺心
        self.state = None

    def init(self): print("Hello, init!")
    def exit(self): print("Goodbye")

lump = Matter()  # 创建实体对象lump

states = [
    {'name': "00", 'on_enter': ['init']},
    {'name': "01"},
    {'name': "02"},
    {'name': "09", 'on_enter': ['exit']},
    {'name': "ERROR"},
]  # 定义状态机的state

transitions = [
    {'trigger': 'zero_to_one', 'source': '00', 'dest': '01'},
    {'trigger': 'zero_to_two', 'source': '00', 'dest': '02'},
    {'trigger': 'two_to_nine', 'source': '02', 'dest': '09'},
    {'trigger': 'any_to_zero', 'source': '*', 'dest': '00'},   # 任意前状态 '*'
    {'trigger': 'any_to_error', 'source': '*', 'dest': 'ERROR'},
]  # 定义状态机的transitions
machine = Machine(model=lump, states=states, transitions=transitions, initial=states[0]['name'])  # 创建状态机对象machine

运行测试

不过多叙述了,自己试试就知道都有什么用了

from transitions import Machine


class Matter(object):
    def __init__(self):
        self.state = None

    def init(self): print("Hello, init!")
    def exit(self): print("Goodbye")


lump = Matter()

states = [
    {'name': "00", 'on_enter': ['init']},
    {'name': "01"},
    {'name': "02"},
    {'name': "09", 'on_exit': ['exit']},
    {'name': "ERROR"},
]


transitions = [
    {'trigger': 'zero_to_one', 'source': '00', 'dest': '01'},
    {'trigger': 'zero_to_two', 'source': '00', 'dest': '02'},
    {'trigger': 'two_to_nine', 'source': '02', 'dest': '09'},
    {'trigger': 'any_to_zero', 'source': '*', 'dest': '00'},   # 任意前状态 '*'
    {'trigger': 'any_to_error', 'source': '*', 'dest': 'ERROR'},
]
# machine.add_states(states=states)
# machine.add_transitions(transitions=transitions)
machine = Machine(model=lump, states=states, transitions=transitions, initial=states[0]['name'])

print(lump.state)
print(machine.get_triggers('00'))
lump.zero_to_two()
print(lump.state)
lump.two_to_nine()
print(lump.state)
lump.any_to_zero()
print(lump.state)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
opengles是一种用于在移动设备和嵌入式系统上实现2D和3D图形渲染的图形。而gl-transitions是一个开源的OpenGL,用于创建平滑过渡效果,可以应用于图像、视频等多种媒体内容。 要将gl-transitions移植到opengles上,需要进行以下步骤: 1. 确定opengles版本:gl-transitions可能使用的是OpenGL的较新版本,而opengles可能只支持较旧的版本。因此,首先需要确定opengles版本,并了解其与OpenGL之间的差异。 2. 了解gl-transitions的实现:深入了解gl-transitions的实现方式和代码结构,理解其对OpenGL的使用方式和功能。 3. 理解opengles的API:熟悉opengles的API,包括顶点/片段着色器、缓冲区对象、纹理对象等。理解opengles的渲染管线和数据传递方式,以便能够正确地将gl-transitions移植到opengles上。 4. 逐步移植:根据gl-transitions的实现和opengles的API,逐步将gl-transitions的代码移植为opengles可用的代码。这可能涉及到对着色器代码的修改、纹理对象的创建和绑定、缓冲区对象的使用等。 5. 调试和测试:移植完成后,进行调试和测试以确保移植后的代码在opengles上正常工作,并且能够正确地渲染出所需的过渡效果。 需要注意的是,由于较新版本的OpenGL可能具有一些opengles不支持的功能,因此在移植过程中可能需要做一些功能的调整或替代。此外,移植过程中可能还需要考虑设备的性能和兼容性问题,确保移植后的代码能够在目标设备上流畅地运行。 总结起来,将gl-transitions移植到opengles上需要对opengles的API有很好的了解,并根据它的渲染方式和数据传递方式对gl-transitions的代码进行适当的修改和调整。这样才能确保移植后的代码能够在opengles上正常运行并呈现出所需的过渡效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值