2017-06-02 114 views
0

我在Python中編寫了一個StateMachine類,所以它可以繼承。 它的邏輯按預期工作,但我可以從State訪問屬性self.data,該屬性存在於派生的StateMachine類中,名稱爲StateMachineTest。產生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())需要selfdata atttribute已設置的事實,但你只把它的下一行(self.data = 10)。切換這兩條線並重試!

+0

這是解決方法,謝謝。我將盡快接受你的答案StackOverflow讓我...... – nbout

0

哇,這個代碼是真的不必要地複雜化。

的問題似乎是,你在你的StateMachineTest類的初始化__init__Started,使其on_enter運行已設置self.data之前。

您可以通過將self.data的任務移到super以上來解決此問題,但更好的辦法是簡化繼承層次結構。

+0

謝謝,那是我的問題。我使用繼承來強制執行'StateMachine'類的可重用性 – nbout