2017-08-25 57 views
-3

我想從一個狀態切換到另一個狀態。每個狀態都由一個函數表示。我想處理在函數內部切換的邏輯,而不是調用該函數的主循環。是否有一個Python庫允許這種模式。 因此,例如:是否有一個python庫,讓你調用函數內的函數,但不會創建遞歸堆棧

def c(count): 
    if count<10: 
     a(count+1) 
     print("dont' keep track of post-order printing") 
    else: 
     print("when count is reached, program should terminate") 
def b(count): 
    c(count): 
def a(count): 
    b(count) 
a() 

這只是一個例子,我試圖用一個有限狀態圖案,其中的邏輯是on_enter方法的過渡中。基本上,機器會自動從一個狀態轉換到下一個狀態,而不使用main_loop。

+0

我可能會看看這個 –

+0

@ user252046的協同程序遞歸的問題是什麼。你爲什麼要「沒有它」? – Rajez

+0

我不希望程序在達到基本情況後回撥。循環永遠持續下去。我知道這可以通過調用函數的主循環來完成,但會造成一大堆混亂。 – user252046

回答

0

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這是標準行爲,您將立即或多或少地發生遞歸錯誤,因爲所有計算機觸發器都將立即處理。

+0

這個完美的作品! – user252046

0

我希望它可能它可能適合你的期望

def c(count): 
    if count<10: 
     print("don't keep track of post-order printing") 
     c(count+1) 
    else: 
     print("when count is reached, program should terminate") 

輸出:

>>> c(1) 
don't keep track of post-order printing 
don't keep track of post-order printing 
don't keep track of post-order printing 
don't keep track of post-order printing 
don't keep track of post-order printing 
don't keep track of post-order printing 
don't keep track of post-order printing 
don't keep track of post-order printing 
don't keep track of post-order printing 
when count is reached, program should terminate