#python #pytransitions
Вопрос:
Я использую библиотеку переходов для Python и нахожу ее действительно полезной. В моем конкретном случае я использую FSMS, которые принимают решения внутри состояний (в обратных вызовах) и соответственно внутренней логике вызывают новые переходы. Например:
states = ["Begin", "CheckCondition", "MakeA", "MakeB", "End"]
transitions = [
["proceed", "Begin", "CheckCondition"],
["path_a", "CheckCondition", "MakeA"],
["path_b", "CheckCondition", "MakeB"],
["proceed", "MakeA", "End"],
["proceed", "MakeB", "End"]
]
class MyModel:
def __str__(self):
return f">>>>> STATE: {self.state}"
def on_enter_CheckCondition(self):
if random.randint(1, 10) > 5:
self.path_a()
return
else:
self.path_b()
return
my_model = MyModel()
machine = HierarchicalGraphMachine(
model=my_model,
states=states,
transitions=transitions,
initial="Begin",
ignore_invalid_triggers=False
)
while my_model.state != "End":
my_model.proceed()
Этот подход сохраняет всю логику внутри FSM, это то, что я хочу, но имеет 2 недостатка:
- У меня потенциально может быть бесконечная цепочка вызовов, которая вызовет переполнение стека (только
proceed()
переход, вызываемыйwhile
циклом, прерывает его). - Я должен помнить, что нужно звонить вручную
return
после вызова любого перехода с обратного вызова
Есть ли лучший способ использовать библиотеку переходов для достижения того, чего я хочу (вызвать переход из обратного вызова)?
Спасибо за помощь!
Ответ №1:
transitions
поддерживает условные переходы, при которых вы можете передать проверку подлинности в качестве обратного вызова для этого перехода. Вы можете довольно легко смоделировать альтернативные пути, предоставив список переходов с различными условиями. Обратите внимание, что переходы оцениваются в том порядке, в котором они были добавлены. Для вашего примера это означает, что вы могли бы написать его следующим образом:
from transitions import Machine
import random
# we do not need 'CheckConditions' when using 'conditions' in transitions
states = ["Begin", "MakeA", "MakeB", "End"]
transitions = [
# when 'proceed' is triggered, 'is_larger_than_5' will be evaluated. The transition is only
# conducted when it evaluates to True.
{"trigger": "proceed", "source": "Begin", "dest": "MakeA", "conditions": ["is_larger_than_5"]},
# This one would be evaluated next. You could add as many checks and paths as you like.
# {"trigger": "proceed", "source": "Begin", "dest": "MakeX", "conditions": ["condition_check"]},
# Otherwise this transition is executed. Since it has no 'conditions' it acts as an 'else' clause.
{"trigger": "proceed", "source": "Begin", "dest": "MakeB"},
# You can specify multiple sources for each transition.
["proceed", ["MakeA", "MakeB"], "End"],
]
class MyModel:
def __str__(self):
return f">>>>> STATE: {self.state}"
# our condition
@staticmethod
def is_larger_than_5():
return random.randint(1, 10) > 5
my_model = MyModel()
machine = Machine(
model=my_model,
states=states,
transitions=transitions,
initial="Begin",
ignore_invalid_triggers=False
)
while my_model.state != "End":
my_model.proceed()
print(my_model)
Это вернется либо:
>>>>> STATE: MakeB
>>>>> STATE: End
или:
>>>>> STATE: MakeA
>>>>> STATE: End
Ответ №2:
Условные переходы поддерживаются переходами, и вы можете передать проверку правильности в качестве обратного вызова для этого перехода. Предоставляя список переходов с различными обстоятельствами, вы можете легко моделировать различные пути. Переходы оцениваются в том порядке, в котором они были добавлены.
Комментарии:
1. Пожалуйста, укажите дополнительную информацию в своем ответе. Как это написано в настоящее время, трудно понять ваше решение.