2017-08-07 88 views
0

我正在使用pytransitions/transitions模塊並嘗試構建一些分層狀態機。分層狀態機:on_enter在嵌套機上調用父方法

在下面的代碼片段中,我觸發了從一個嵌套狀態到另一個狀態的轉換。

問題是,如果我將on_enter回調附加到目標嵌套狀態,庫正在父機器中搜索此回調。

from transitions.extensions import HierarchicalMachine as Machine 
from transitions.extensions.nesting import NestedState as State 

class Nested(Machine): 
    def print_msg(self): 
     print("Nested") 
    def __init__(self): 
     self.states = ['n1', {'name':'n2', 'on_enter':'print_msg'}] 
     Machine.__init__(self, states=self.states, initial='n1') 
     self.add_transition(trigger='goto_n2', 
          source='*', 
          dest='n2') 

class Top(Machine): 
    def print_msg(self): 
     print("Top") 
    def __init__(self): 
     self.nested = Nested() 

     self.states = [ 't1', 
         {'name': 't2', 
         'children': self.nested}] 
     Machine.__init__(self, states=self.states, initial='t1') 
     self.add_transition(trigger='goto_t2', 
          source='*', 
          dest='t2_n1') 



top_machine = Top() 
top_machine.goto_t2() 
top_machine.goto_n2() 

腳本的輸出是「頂級」

如果我從頂級刪除print_msg(),然後我得到AttributeError的。

雖然理論上我可以在頂級機器中進行回調,但我肯定會更喜歡將我的狀態和回調保存在嵌套機器的明確界限中。

任何想法如何實現它?

回答

0

從相關Github上issue

字符串回調的模型,你的情況是頂級的機器總是擡頭。 如果您沒有將特定模型實例傳遞給Machine,它將作爲模型本身。 對於更復雜的場景,我建議分割機器(轉換和相關規則) 和模型(基於實際狀態的行爲)。

當您將Machine實例傳遞給另一個HSM時,規則和轉換將被複制,而不僅僅是重用。這就是爲什麼Nested將使用自己作爲模型,但嵌套版本將使用Top來代替。僅擁有Nested的資產副本有兩個優點:首先,它不會干預原始的嵌套實例;其次,它允許重用由核心提供的許多功能,否則這些功能必須重寫,因此會導致更高的代碼複雜性。

'最簡單'的方法是通過引用而不是按名稱傳遞迴調。而不是'on_enter':'print_msg'使用'on_enter':self.print_msg。通過這種方式,回調參考已經解決,防止轉換在模型中查找它(注意:這已被竊聽,直到轉換0.6.1)。

from transitions.extensions import HierarchicalMachine as Machine 


class Nested(Machine): 

    def __init__(self, parent): 
     self.parent = parent 
     states = ['1', {'name': '2', 'on_enter': self.print_msg}] 
     transitions = [['finish', '*', '2']] 
     super(Nested, self).__init__(states=states, transitions=transitions, 
            initial='1') 

    def print_msg(self): 
     print("Nested") 
     self.parent.print_top() 


class Top(Machine): 

    def print_msg(self): 
     print("Top") 

    def __init__(self): 
     self.nested = Nested(self) 

     states = ['A', {'name': 'B', 'children': self.nested}] 
     transitions = [dict(trigger='print_top', source='*', 
          dest='=', after=self.print_msg), 
         dict(trigger='to_nested', source='*', 
          dest='B_1')] 

     super(Top, self).__init__(states=states, transitions=transitions, 
            initial='A') 

top_machine = Top() 
top_machine.to_nested() 
top_machine.finish() 

如上所述,我也建議分裂機和模型。通過這種方式,您可以使用MixIns來修飾主模型,並使代碼更簡潔。這樣你也可以使用OOP提供的每個工具來改變狀態機的行爲。