来自Ruby世界,我们有美丽的状态机框架like the one recently baked into Rails,我很惊讶在Python中找不到具有相似美感的明显候选人。我想避免自己动手;面向对象的状态机设计通常要求您在每次添加状态时吊起一堆python(在这种情况下我会经常这样做)。
我应该在Python代码中使用的状态机的框架是什么?在进行任何性能或其他考虑之前,我想要最优雅的代码。
你可以尝试这个片段
我正在寻找相同的,到目前为止xworkflow似乎是我能找到的最佳人选。
虽然我对python很新,但在我看来,没有标准的库可以用于所有东西,但是社区提供了大量独立的实现,有些比其他的更加pythonic,但最终它们中的大多数很棒我找到的其他实现如下所示。
我经常只使用dict来进行状态机描述。根据应用程序,键可能是(状态,事件),因此值可能是(new_state,args)。例如:
machine = {
('state_a', 'x'): ('state_b', 'arg1'),
('state_b', 'y'): ('state_c', 'arg2'),
...
}
读取和执行该dict的类,函数或生成器可以非常简单,具体取决于您希望转换的工作方式。例如,使用python最近的.send()方法的生成器可能是编写简单事件驱动的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
...
我知道这有点晚了,但只是做了一些研究并发现了这篇文章。我在我的django-ostinato项目中编写了自己的Statemachine。
https://github.com/andrewebdev/django-ostinato/blob/master/ostinato/statemachine/core.py
文档:https://django-ostinato.readthedocs.org/en/latest/ostinato.statemachine.html
编写状态机是为了不需要直接集成到django模型中,但是您可以使用模型实例对其进行初始化。我一直在使用它来完成一些复杂的状态机工作。
此外,状态机是框架无关的,因为您只是传递一个对象实例。您只需确保实例具有包含实际状态的属性。
可能有更好的方法,但到目前为止这对我有好处。
一些较新的竞争者(分别来自2014年和2016年):
在pyparsing示例中包含一个状态机Python语言扩展,它允许您导入包含状态机规范的.pystate
文件,格式如下:
#
# librarybookstate.pystate
#
# This state machine models the state of books in a library.
#
statemachine BookState:
New -(shelve)-> Available
Available -(reserve)-> OnHold
OnHold -(release)-> Available
Available -(checkout)-> CheckedOut
CheckedOut -(checkin)-> Available
然后Python代码像常规模块一样导入它:
import statemachine
import librarybookstate
class Book(librarybookstate.BookStateMixin):
def __init__(self):
self.initialize_state(librarybookstate.New())
添加一些引用作为这个问题是古老的,需要更新的答案。
纯python状态机: https://github.com/pytransitions/transitions
Django支持状态机:https://github.com/viewflow/django-fsm