transitionsは、あなたが探しているかもしれないqueued
トランジションだけでなく、順序付きトランジションも備えています。基本的なやり方は、全く同じイベントが処理されるたびに(finalize
で)同じイベントを呼び出すことです。 finalize
に渡されたコールバックは、移行が成功していない場合でも処理されます(すべてconditions
が返されます)。True
が返されます。 queued
のトランジションでは、直ちにイベントを処理することはなく、現在処理されているイベントの直後に大量の再帰を防ぐことができます。
from transitions import Machine
import time
class Model(object):
# initialise counter and counter limit
def __init__(self):
self.counter = 0
self.limit = 5
# will be called in every cycle and increase the counter
def increase_counter(self):
self.counter += 1
print("Counter increased to ", self.counter)
time.sleep(0.5)
# will be called whenever a new state has been entered
def reset_counter(self):
self.counter = 0
print("Counter reset; Current state is ", model.state)
# this function returns whether the limit has already been reached
def limit_reached(self):
return self.counter >= self.limit
# initialising the previously defined model
model = Model()
# creating some state names
states = ['A', 'B', 'C', 'D']
# configuring the state machine:
# pass the model (for callbacks), pass the state names,
# disable auto_transitions since we will not need them
# set the initial state to 'A' and call a (currently) undefined
# model function 'next_state' after EVERY triggered event.
# 'queued' means that every transition is finished before the next event is handled
machine = Machine(model, states=states, auto_transitions=False,
queued=True, initial='A', finalize_event='next_state')
# now add ordered transitions:
# Depending on the order of the passed state names,
# create transitions from each state 'n' to state 'n+1' called 'next_state'.
# 'prepare' each transition attempt by increasing the counter
# afterwards check the 'conditions' (is the counter limit reached)
# if all callbacks in 'conditions' return True, the transition
# is conducted and callbacks in 'after' are processed (counter reset)
machine.add_ordered_transitions(prepare='increase_counter', conditions='limit_reached',
after='reset_counter', trigger='next_state')
# model will go into an infinite loop; can be triggered in a thread
model.next_state()
あなたは(あなたがいけない)再帰エラーがヒットするかどうかを確認するためにincrease_counter
にスリープタイマーを削減しようとすることができます。標準的な動作であるqueued=False
を設定した場合、すべてのマシントリガーが即座に処理されるため、再帰エラーが多少なりとも発生します。
私はこのコルーチンをおそらく見るでしょう –
@ user252046再帰的な問題は何ですか?なぜあなたは "それなし"を望んでいますか? – Rajez
ベースケースに達した後にプログラムがコールバックしないようにしたい。そしてループは永遠に続く。私はそれが関数を呼び出すメインループを持つことによって達成することができますが、それは混乱の全体をたくさん作成するだろう知っている。 – user252046