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)

三种实现对比

  • 第一种实现 很简洁 但是不够透明
  • 第二种相对灵活 可以实现复杂业务和场景
  • 第三种实现 业务如果复杂 则相对代码耦合度高 不利于拓展
posted @ 2025-03-06 20:39  vx_guanchaoguo0  阅读(35)  评论(0)    收藏  举报