python FSM 有限状态机
第三方库实现代码实现
from transitions import Machine
# 定义一个自己的类
class Matter(object):
pass
model = Matter()
"""
liquid
- -
- -
melt - - evaporate
- -
- sublimate - ionize
solid - - - - - - - - - - - - - gas - - - - - - - plasma
"""
# 状态定义
states = ['solid', 'liquid', 'gas', 'plasma']
# 定义状态转移
# The trigger argument defines the name of the new triggering method
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=model, states=states, transitions=transitions, initial='solid')
if __name__ == '__main__':
# Test
print(model.state) # solid
# 状体转变
model.melt()
print(model.state) # liquid
自己实现的状态机
"""
liquid
- -
- -
melt - - evaporate
- -
- sublimate - ionize
solid - - - - - - - - - - - - - gas - - - - - - - plasma
"""
class InitializationError(Exception):
pass
class StateMachine:
def __init__(self, model, states, transitions, initial_state):
self.model = model
self.states = states
self.initial_state = initial_state
self.handlers = {}
self.startState = None
self.endStates = []
self.transitions = transitions
def add_state(self, name, handler, end_state=0):
name = name.lower() # 使用小写字母来表示状态
if name not in self.states:
raise InitializationError("State '{}' not found.".format(name))
self.handlers[name] = handler
if end_state:
self.endStates.append(name)
def set_start(self, name):
self.startState = name.lower()
def run(self, transition):
self.model.state = self.model.state if self.model.state else self.initial_state
try:
if transition not in self.transitions:
raise InitializationError("transition '{}' not found.".format(transition))
handler = self.handlers[self.model.state]
except:
raise InitializationError("must call .set_start() before .run()")
if not self.endStates:
raise InitializationError("at least one state must be an end_state")
while True:
self.model.state, next_transition, transition = handler(transition)
if self.model.state in self.endStates:
print("reached ", self.model.state)
break
elif not transition:
break
else:
handler = self.handlers[self.model.state]
transition = None
class Matter(object):
state = None
# 定义状态转换相关的函数
def solid_state_transitions(txt):
if txt == "melt":
newState, newTransition = "liquid", 'evaporate'
elif txt == "sublimate":
newState, newTransition = "gas", 'ionize'
else:
newState, newTransition = "error", None
return newState, newTransition, None
def liquid_state_transitions(txt):
if txt == "evaporate":
newState, newTransition = "gas", 'ionize'
else:
newState, newTransition = "error", None
return newState, newTransition, None
def gas_state_transitions(txt):
if txt == "ionize":
newState, newTransition = "plasma", None
else:
newState, newTransition = "error", None
return newState, newTransition, None
def error_state(txt):
print("Error: Invalid transition!")
return "error", ""
if __name__ == '__main__':
# 创建状态机
states = ['solid', 'liquid', 'gas', 'plasma', 'error']
transitions = ['melt', 'evaporate', 'sublimate', 'ionize']
obj = Matter()
m = StateMachine(model=obj, states=states, transitions=transitions, initial_state='solid')
m.add_state("solid", solid_state_transitions)
m.add_state("liquid", liquid_state_transitions)
m.add_state("gas", gas_state_transitions)
m.add_state("error", None, end_state=1)
# 设置起始状态
m.set_start("solid")
# 运行状态机,模拟状态转换
m.run("melt") # solid -> liquid
print(obj.state)
m.run("evaporate") # liquid -> gas
print(obj.state)
m.run("ionize") # gas -> plasma
print(obj.state)
# m.run("ionize") # plasma -> error (invalid transition)
利用魔术方法实现精简版本
"""
liquid
- -
- -
melt - - evaporate
- -
- sublimate - ionize
solid - - - - - - - - - - - - - gas - - - - - - - plasma
"""
class InitializationError(Exception):
pass
class StateMachine:
def __init__(self, model, states, transitions, initial_state):
self.model = model
self.model.transitions = transitions
self.model.state = initial_state
self.model.states = states
class Matter(object):
def __getattr__(self, name):
def method(*args, **kwargs):
for _ in self.transitions:
if _.get('source') not in self.states or _.get('dest') not in self.states:
print("Error: Invalid transition!")
break
if _.get('trigger') == name:
if _.get('source') != self.state:
print("Error: Invalid transition!")
self.state = _.get('dest')
break
return method
state = None
states = None
transitions = None
if __name__ == '__main__':
# 创建状态机
states = ['solid', 'liquid', 'gas', 'plasma', 'error']
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'}
]
obj = Matter()
m = StateMachine(model=obj, states=states, transitions=transitions, initial_state='solid')
print(obj.state)
obj.melt()
print(obj.state)
三种实现对比
- 第一种实现 很简洁 但是不够透明
- 第二种相对灵活 可以实现复杂业务和场景
- 第三种实现 业务如果复杂 则相对代码耦合度高 不利于拓展
本文来自博客园,作者:vx_guanchaoguo0,转载请注明原文链接:https://www.cnblogs.com/guanchaoguo/p/18756342

浙公网安备 33010602011771号