Last active
February 11, 2020 08:51
-
-
Save 4e1e0603/0fd31b9072107e20daac5106fe061c6b to your computer and use it in GitHub Desktop.
Example of State Machine with Switch Statement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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