2017-06-02 3 views
0

J'ai écrit une classe StateMachine en Python afin de pouvoir en hériter. La logique de ce travail fonctionne comme prévu mais je peux accéder à l'attribut self.data à partir d'un State qui est présent dans la classe StateMachine dérivée nommée StateMachineTest.Héritage de classe Python, attributeError

L'erreur suivante est générée:

 
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() 

Répondre

0

Votre problème réside dans le fait que StateMachine.__init__(self, Started()) exige self « s data atttribute être déjà défini, mais vous définissez seulement elle la ligne suivante (self.data = 10). Changez ces deux lignes et réessayez!

+0

Ceci est la solution, merci. J'accepterai votre réponse dès que StackOverflow me laissera ... – nbout

0

Wow, ce code est vraiment inutilement compliqué.

Le problème semble être que vous initialisez Started dans la __init__ de votre classe StateMachineTest, de sorte que ses on_enter exécute avant que vous avez défini self.data.

Vous pouvez peut-être résoudre ce problème en déplaçant l'affectation de self.data au-dessus de l'appel super, mais un bien meilleur résultat serait de simplifier votre hiérarchie d'héritage.

+0

Merci, c'était mon problème. J'ai utilisé l'héritage de cette façon à la réutilisation forcée de la classe 'StateMachine' – nbout