Python state-machine design

后端 未结 12 2130
予麋鹿
予麋鹿 2020-11-30 17:36

Related to this Stack Overflow question (C state-machine design), could you Stack Overflow folks share your Python state-machine design techniques

12条回答
  •  Happy的楠姐
    2020-11-30 18:21

    I don't really get the question. The State Design pattern is pretty clear. See the Design Patterns book.

    class SuperState( object ):
        def someStatefulMethod( self ):
            raise NotImplementedError()
        def transitionRule( self, input ):
            raise NotImplementedError()
    
    class SomeState( SuperState ):
        def someStatefulMethod( self ):
            actually do something()
        def transitionRule( self, input ):
            return NextState()
    

    That's pretty common boilerplate, used in Java, C++, Python (and I'm sure other languages, also).

    If your state transition rules happen to be trivial, there are some optimizations to push the transition rule itself into the superclass.

    Note that we need to have forward references, so we refer to classes by name, and use eval to translate a class name to an actual class. The alternative is to make the transition rules instance variables instead of class variables and then create the instances after all the classes are defined.

    class State( object ):
        def transitionRule( self, input ):
            return eval(self.map[input])()
    
    class S1( State ): 
        map = { "input": "S2", "other": "S3" }
        pass # Overrides to state-specific methods
    
    class S2( State ):
        map = { "foo": "S1", "bar": "S2" }
    
    class S3( State ):
        map = { "quux": "S1" }
    

    In some cases, your event isn't as simple as testing objects for equality, so a more general transition rule is to use a proper list of function-object pairs.

    class State( object ):
        def transitionRule( self, input ):
            next_states = [ s for f,s in self.map if f(input)  ]
            assert len(next_states) >= 1, "faulty transition rule"
            return eval(next_states[0])()
    
    class S1( State ):
        map = [ (lambda x: x == "input", "S2"), (lambda x: x == "other", "S3" ) ]
    
    class S2( State ):
        map = [ (lambda x: "bar" <= x <= "foo", "S3"), (lambda x: True, "S1") ]
    

    Since the rules are evaluated sequentially, this allows a "default" rule.

提交回复
热议问题