Skip to content

Instantly share code, notes, and snippets.

@4e1e0603
Last active February 11, 2020 08:51
Show Gist options
  • Save 4e1e0603/0fd31b9072107e20daac5106fe061c6b to your computer and use it in GitHub Desktop.
Save 4e1e0603/0fd31b9072107e20daac5106fe061c6b to your computer and use it in GitHub Desktop.
Example of State Machine with Switch Statement
"""
Simple state machine example and switch emulation.
"""
from enum import Enum
from typing import Iterable
class State(Enum):
OPENED = 1
CLOSED = 2
class Action(Enum):
OPEN = 1
CLOSE = 2
def update(state: State, action: Action) -> State:
# Update function in the Elm style:
# https://elmprogramming.com/model-view-update-part-1.html
return {
(State.CLOSED, Action.OPEN): State.OPENED,
(State.OPENED, Action.CLOSE): State.CLOSED,
}[(state, action)]
class Machine:
"""
Creates a state machine as mutable object.
"""
def __init__(self, *states: State):
self._states = tuple(states)
@property
def state(self):
"""
Gets a current states.
"""
return self._states[-1]
@property
def states(self):
"""
Gets a past and current state.
"""
return self._states
def update(self, action: Action) -> 'Machine':
"""
Update the machine state.
"""
state = {
(State.CLOSED, Action.OPEN): State.OPENED,
(State.OPENED, Action.CLOSE): State.CLOSED,
}[(self.state, action)]
self._states += (state,)
def updated(self, action: Action) -> 'Machine':
"""
Get a new machine with updated state.
"""
machine = (Machine(*self.states))
machine.update(action)
return machine
if __name__ == '__main__':
print("-----------------------------------------------------------------------")
print("1. Functional style `State -> Action -> State`.")
print("-----------------------------------------------------------------------")
door_state = State.OPENED
door_state = update(door_state, Action.CLOSE)
print(door_state)
print("-----------------------------------------------------------------------")
print("2. Object oriented style with mutable object.")
print("-----------------------------------------------------------------------")
door = Machine(State.OPENED)
door.update(Action.CLOSE)
door.update(Action.OPEN)
door.update(Action.CLOSE)
door.update(Action.OPEN)
print(door.states)
print("-----------------------------------------------------------------------")
print("3. Object oriented style with immutable object.")
# This should be separated class, but for this example
# we put the updated method to the existing object
print("-----------------------------------------------------------------------")
door_2 = door.updated(Action.CLOSE)
print(door_2.states)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment