2017-08-07 10 views
0

私はpytransitions/transitionモジュールを使用しており、いくつかの階層的な状態マシンを構築しようとしています。階層的状態マシン:ネストされたマシンコールの親メソッドのon_enter

以下のスニペットでは、1つの入れ子状態から別の入れ子状態への移行を開始しています。

問題は、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を取得しています。

理論上私はトップマシンでコールバックを持つことができますが、私は自分の状態とコールバックをネストされたマシンの明確に定義された境界に保つことをお勧めします。

どのようにそれを達成するためのアイデアですか?関連Githubのissueから

答えて

0

文字列のコールバックは、常にあなたのケースでトップのマシンであるモデルの中で検索されています。 特定のモデルインスタンスをMachineに渡さないと、モデル自体として機能します。 もっと複雑なシナリオについては、マシン(遷移と関連ルール)を分割して とモデル(実際の状態に基づいた動作)を行うことをお勧めします。

Machineインスタンスを別のHSMに渡すと、ルールとトランジションがコピーされ、再利用されるだけではありません。だからNestedはそれ自体をモデルとして使用しますが、ネストされたバージョンは代わりにTopを使用します。 Nestedのアセットのコピーを持つことには2つの利点があります。まず、元のネストされたインスタンスに介入せず、2番目に、コアによって提供される多くの機能を再利用することができます。

'最も簡単な方法は、コールバックを名前ではなく参照で渡すことです。 '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() 

上記のように、マシンとモデルの分割もお勧めします。このようにして、MixInを使用してメインモデルを飾り、コードの混乱を避けることができます。このようにして、OOPが提供するすべてのツールを使用して、ステートマシンの動作を変更することもできます。

関連する問題