A menudo solo uso un dict para la descripción de la máquina de estado. Dependiendo de la aplicación, las claves podrían ser (estado, evento), los valores podrían ser (new_state, args). Por ejemplo:
machine = {
('state_a', 'x'): ('state_b', 'arg1'),
('state_b', 'y'): ('state_c', 'arg2'),
...
}
La clase, función o generador de leer y ejecutar ese dict puede ser bastante simple, dependiendo de cómo desea que sus transiciones hacia el trabajo. Un generador que utilice el método .send() más reciente de python podría ser una forma de escribir un componente simple Model-View-Controller impulsado por eventos, por ejemplo. El uso de devoluciones de llamadas en lugar de cadenas para estados y/o eventos eliminará la necesidad de una gran cantidad de código si/entonces también.
Sé que esto es "renovar el suyo", pero en la práctica he descubierto que todo esto cabe en un par de docenas de líneas de código, dependiendo del tamaño de la máquina de estado, y se puede adaptar para adaptarse a la aplicación mejor que el marco genérico típico. A menudo requiere menos código de configuración que esos marcos también.
Aquí hay un ejemplo un poco más completo, utilizando devoluciones de llamada para el estado: este es el tipo de cosas que haría si siempre desea ejecutar el mismo código en la entrada de estado. (El uso de devoluciones de llamada de eventos le daría código específico para la transición en su lugar.):
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
Aquí está la salida:
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
...
"diseños orientados a objetos de máquinas de estado por lo general requieren que se honda un montón de pitón cada vez que añada un estado"? De Verdad? Todo lo que hice fue agregar una clase y modificar las diversas reglas de transición. El diseño ** Estandarte ** de pandillas funciona para mí. ¿Por qué no funciona para ti? ¿Tienes ejemplos? –
Oh, funciona, funciona bien. No me importa hacerlo si el conjunto de estados es generalmente estable. En este caso, voy a terminar modificando la máquina de estados en básicamente todos los casos de prueba: escribir una nueva clase cada vez parece un poco complicado. –
Además, definir la misma clase de "Estado" que todos los demás sienten repetitiva; Prefiero usar una clase estatal canónica, al menos. –