Related to this Stack Overflow question (C state-machine design), could you Stack Overflow folks share your Python state-machine design techniques with me (and the community)?
At the moment, I am going for an engine based on the following:
class TrackInfoHandler(object):
def __init__(self):
self._state="begin"
self._acc=""
## ================================== Event callbacks
def startElement(self, name, attrs):
self._dispatch(("startElement", name, attrs))
def characters(self, ch):
self._acc+=ch
def endElement(self, name):
self._dispatch(("endElement", self._acc))
self._acc=""
## ===================================
def _missingState(self, _event):
raise HandlerException("missing state(%s)" % self._state)
def _dispatch(self, event):
methodName="st_"+self._state
getattr(self, methodName, self._missingState)(event)
## =================================== State related callbacks
But I am sure there are tons of ways of going at it while leveraging Python's dynamic nature (e.g. dynamic dispatching).
I am after design techniques for the "engine" that receives the "events" and "dispatches" against those based on the "state" of the machine.
The following code is a really simple solution. The only interesting part is:
All the logic for each state is contained in a separate class. The 'state' is changed by replacing the '__class__' of the running instance.
Result:
Other related projects:
http://fsme.sourceforge.net/
https://code.google.com/p/visio2python/
You can paint state-machine and then use it in your code.
I would definitely not recommend implementing such a well known pattern yourself. Just go for an open source implementation like transitions and wrap another class around it if you need custom features. In this post I explain why I prefer this particular implementation and its features.
I don't really get the question. The State Design pattern is pretty clear. See the Design Patterns book.
That's pretty common boilerplate, used in Java, C++, Python (and I'm sure other languages, also).
If your state transition rules happen to be trivial, there are some optimizations to push the transition rule itself into the superclass.
Note that we need to have forward references, so we refer to classes by name, and use
eval
to translate a class name to an actual class. The alternative is to make the transition rules instance variables instead of class variables and then create the instances after all the classes are defined.In some cases, your event isn't as simple as testing objects for equality, so a more general transition rule is to use a proper list of function-object pairs.
Since the rules are evaluated sequentially, this allows a "default" rule.
I also was not happy with the current options for state_machines so I wrote the state_machine library.
You can install it by
pip install state_machine
and use it like so:It probably depends on how complex your state machine is. For simple state machines, a dict of dicts (of event-keys to state-keys for DFAs, or event-keys to lists/sets/tuples of state-keys for NFAs) will probably be the simplest thing to write and understand.
For more complex state machines, I've heard good things about SMC, which can compile declarative state machine descriptions to code in a wide variety of languages, including Python.