Reputation: 1363
The problem I'm trying to solve is-- I have a python application that accepts user input in a variety of ways and raises events based on those inputs. I am wanting to usE a finite state machine to handle the states transitions and currently have the graph of the finite state machine represented in the python code itself.
Here's what I've tried so far by implementing the equivalent of a big switch statement in python, like this:
if input == 0 and prev_state == 1:
cur_state = 3
elif input == 1 and prev_state == 2:
cur_state = 4
This is clumsy and error prone, so I'd like to move this graph definition of this outside of the python code and into a separate file that's using something like BNF, or similar, to make it easier to manage the finite state machine graph.
The fsm graph file might look something like this:
current_state == 1 and input == 2 -> next_state = 0
The python code might look something like this (psuedo):
fms = MyFsm("my_graph.txt")
while(True):
input = console.get_input()
current_state = fsm.transition(previous_state, input)
My question is: how can I represent a finite state machine in python without using a bunch of if / elif statements?
Upvotes: 1
Views: 2104
Reputation: 1257
Yes, your gut feeling is correct that the if/else/switch approach to managing state is error prone. While it can be fine for smaller FSMs, they can grow unwieldy pretty quickly.
If you're input is a single value, then one simple approach for managing this in Python would be to use a dictionary to map current state and input to transition state. For example,
map = [
{ 'input': 0, 'current_state': 0, 'transition_state': 1 },
{ 'input': 0, 'current_state': 1, 'transition_state': 0 },
]
Then your state transition code would simply search for the right transition state based on the values of input
and current_state
. For example,
def lookup(input, state):
transition_state = None
for item in map:
if item.current_state == state and item.input == input:
transition_state = item.transition_state
return transition_state
This is better than the if
/elif
approach since you're separating the FSM transitions from the python code itself, which then makes it possible and much easier to load the FSM dataset from an external file, database, etc.
Upvotes: 2