2017-06-02 24 views
0

私はStateMachineクラスをPythonで書いたので、継承できます。 そのロジックは期待通りに機能しますが、派生型StateMachineクラスStateMachineTestに存在するStateから属性self.dataにアクセスできます。Pythonクラスの継承、attributeError

次のエラーが生成されます

 
Traceback (most recent call last): 
File "/home/nbout/work/python/state_machine/main.py", line 68, in 
    main() 
File "/home/nbout/work/python/state_machine/main.py", line 59, in main 
    test = StateMachineTest() 
File "/home/nbout/work/python/state_machine/main.py", line 47, in __init__ 
    StateMachine.__init__(self, Started()) 
File "/home/nbout/work/python/state_machine/state_machine.py", line 17, in _init__ 
    self.current_state.on_enter(self) 
File "/home/nbout/work/python/state_machine/main.py", line 16, in on_enter 
    print("Started: data:{}".format(sm_test.data)) 
Started: on_enter 
AttributeError: 'StateMachineTest' object has no attribute 'data' 
Started: on_exit 

state_machine.py

class State: 

    def on_enter(self, state_machine): 
     pass 

    def on_exit(self, state_machine): 
     pass 


class StateMachine: 

    def __init__(self, start_state): 
     self.current_state = start_state 

     self.current_state.on_enter(self) 

    def __del__(self): 
     self.current_state.on_exit(self) 

    def set_state(self, state): 

     self.current_state.on_exit(self) 
     self.current_state = state 
     self.current_state.on_enter(self) 

main.py

from state_machine import StateMachine 
from state_machine import State 


class StateTest(State): 
    def pause(self, state_machine_test): 
     pass 

    def start(self, state_machine_test): 
     pass 


class Started(StateTest): 
    def on_enter(self, sm_test): 
     print("Started: on_enter") 
     print("Started: data:{}".format(sm_test.data)) 

    def on_exit(self, sm_test): 
     print("Started: on_exit") 

    def pause(self, sm_test): 
     print("Started: pause") 
     sm_test.set_state(Paused()) 

    def start(self, sm_test): 
     print("Started: start") 


class Paused(StateTest): 
    def on_enter(self, sm_test): 
     print("Paused: on_enter") 

    def on_exit(self, sm_test): 
     print("Paused: on_exit") 

    def pause(self, sm_test): 
     print("Paused: pause") 

    def start(self, sm_test): 
     print("Paused: start") 
     sm_test.set_state(Started()) 


class StateMachineTest(StateMachine): 

    def __init__(self): 
     StateMachine.__init__(self, Started()) 
     self.data = 10 

    def pause(self): 
     self.current_state.pause(self) 

    def start(self): 
     self.current_state.start(self) 


def main(): 

    test = StateMachineTest() 

    test.start() 
    test.pause() 
    test.pause() 
    test.start() 


if __name__ == '__main__': 
    main() 

答えて

0

あなたの問題はStateMachine.__init__(self, Started())がすでに設定されてselfさんdata atttributeが必要ですが、あなただけそれを次の行(self.data = 10)を設定することです。これらの2つの線を切り替えて、もう一度やり直してください!

+0

これは解決策です、ありがとうございます。私はStackOverflowが私に教えてくれたらすぐにあなたの答えを受け入れます... – nbout

0

うわー、このコードは実際に不必要に複雑になります。

問題は、あなたがself.dataを設定しているそのon_enter実行前になるようにあなたは、あなたのStateMachineTestクラスの__init__Startedを初期化することであるように思われます。

self.dataの割り当てをsuperコールよりも上に移動することでこれを解決できる可能性がありますが、継承階層を単純化する方がはるかに優れています。

+0

ありがとう、それは私の問題でした。私は 'StateMachine'クラスの再利用性を強制するために継承を使用しました – nbout