我在嵌套机器中使用条件转换。不幸的是,条件方法无法访问类属性self._error。所以我必须将属性传递给触发方法。该解决方案有效,但我必须注意将正确的属性传递给触发方法。
我想使用另一种解决方案,它在没有传递参数的情况下工作,但我不知道是否可以使用 pytransitions 来实现它。
GenericMachine是定义基本状态和配置的抽象类。
from transitions.extensions import HierarchicalMachine
class GenericMachine(HierarchicalMachine):
def __init__(self, states, transitions, model=None):
generic_states = [
{"name": "initial", "on_enter": self.entry_initial},
{"name": "done"},
]
states += generic_states
super().__init__(
states=states,
transitions=transitions,
model=model,
send_event=True,
queued=False,
)
def entry_initial(self, event_data):
raise NotImplementedError
MainMachine定义层次结构中的最高机器并实例化NestedMachine
class MainMachine(GenericMachine):
def __init__(self):
nested = NestedMachine()
remap = {"done": "done"}
states = [
{"name": "nested", "children": nested, "remap": remap},
]
transitions = [
["go", "initial", "nested"],
]
super().__init__(states, transitions, model=self)
魔法发生在这里NestedMachine。条件在error方法中得到解决。但是该方法只能看到self._error属性的初始值,所以initial状态的变化并没有体现出来。
class NestedMachine(GenericMachine):
def __init__(self):
self._error = None
states = [
{"name": "error"},
]
transitions = [
{
"trigger": "go",
"source": "initial",
"dest": "error",
"conditions": self.error,
},
{
"trigger": "go",
"source": "initial",
"dest": "done",
"unless": self.error,
},
]
super().__init__(states, transitions)
def error(self, event_data):
return self._error
def entry_initial(self, event_data):
self._error = True
event_data.model.go()
测试用例预计在 结束nested_error,但nested_initial在"go"事件未执行时结束
def main():
machine = MainMachine()
machine.go()
assert machine.state == "nested_error"
if __name__ == "__main__":
main()
解决方法是将属性传递给触发函数,然后它按预期工作。
def error(self, event_data):
error = event_data.kwargs["error"]
return error
def entry_initial(self, event_data):
self._error = True
event_data.model.go(error=self._error)
并且可能最好的解决方案是使用属性装饰器,而我error不仅可以将属性用于转换。
@property
def error(self):
return self._error
def entry_initial(self, event_data):
self._error = True
event_data.model.go()