Я часто просто использую dict для описания конечного автомата. В зависимости от приложения, ключи могут быть (состояние, событие), значения могут быть (new_state, args). Например:
machine = {
('state_a', 'x'): ('state_b', 'arg1'),
('state_b', 'y'): ('state_c', 'arg2'),
...
}
Класс, функция или генератор для чтения и выполнения этого dict могут быть довольно простыми, в зависимости от того, как вы хотите, чтобы ваши переходы работали. Например, генератор, использующий более поздний метод .send () python, может быть одним из способов написания простого компонента Model-View-Controller, управляемого событиями. Использование обратных вызовов вместо строк для состояний и / или событий устранит необходимость в большом количестве кода if / then.
Я знаю, что это «катит сам по себе», но на практике я обнаружил, что все это вписывается в пару десятков строк кода, в зависимости от размера конечного автомата, и может быть адаптировано для приложения лучше чем типичные общие рамки. Часто для этого требуется меньше установочного кода, чем для этих фреймворков.
Вот немного более полный пример, использующий обратные вызовы для состояния - это то, что вы должны делать, если вы всегда хотите выполнять один и тот же код при входе в состояние. (Использование обратных вызовов для событий даст вам код, специфичный для перехода.):
def foo(x):
print 'foo got', x
return 'x'
def bar(x):
print 'bar got', x
return 'y'
def baz(x):
print 'baz got', x
return 'z'
machine = {
(foo, 'x'): (bar, 'arg1'),
(bar, 'y'): (baz, 'arg2'),
(baz, 'z'): (foo, 'arg3'),
}
state,arg = foo,'arg0'
while True:
event = state(arg)
res = machine.get((state, event))
if not res:
print "halting on", state, event
break
state,arg = res
Вот вывод:
foo got arg0
bar got arg1
baz got arg2
foo got arg3
bar got arg1
baz got arg2
foo got arg3
bar got arg1
baz got arg2
foo got arg3
...