Python - 使用globals()与代码可读性

时间:2014-04-13 15:59:18

标签: python design-patterns state-machine

我正在python中实现状态设计模式的可靠实现。在这样做的过程中,我发现了两种做事方式。

方式1

class State(object):
    transitions = [(None, None, None)]
    def __init__(self, state_context):
        self._context = state_context
        self.set_transitions()

    def set_transitions(self):
        """subclass may override this if access to self is
        needed in transitions"""
        pass

    def __call__(self, inp):
        new_state = self
        state_action_list = [(state, action) for cls, state,
                     action in self.transitions if
                     isinstance(inp, cls)]
        if 1 == len(state_action_list):
            state, action = state_action_list[0]
            if action is not None:
                action(inp)
            new_state = globals()[state](self._context)
        elif 1 < len(state_action_list):
            raise AmbiguousTransitionError(inp, self)    
        return new_state

允许这种用法:

class StateA(State):
    transitions = [(MsgA, "StateB", None)]

class StateB(State):
    def set_transitions(self):
        self.transitions = [(MsgB, "StateC", self._print_msg)]

    @staticmethod
    def _print_msg(inp):
        print "Inp: ", inp

class StateC(State):
    def set_transitions(self):
        self.transitions = [(MsgB, "StateB", None),
                    (MsgC, "StateA", self._print_context)]

    def _print_context(self, unused_inp):
        """example"""
        print "Context: ", self._context

这里是Way 2的改变

    def __call__(self, inp):
        [...]
        if action is not None:
            try:
                action(inp)
            except TypeError:
                action(self, inp)
            new_state = state(self._context)
        [...]

用法:

class StateA(State): pass
class StateB(State):
    @staticmethod
    def _print_msg(inp):
        print "Inp: ", inp

class StateC(State):
    def _print_context(self, unused_inp):
        """example"""
        print "Context: ", self._context

StateA.transitions = [(MsgA, StateB, None)]
StateB.transitions = [(MsgB, StateC, StateB._print_msg)]
StateC.transitions = [(MsgB, StateB, None),
              (MsgC, StateA, StateC._print_context)]

我遇到的问题是:

  • 状态名称中的拼写错误将在运行时失败/同样错误的方式2甚至不会启动
  • 我必须使用globals()来上课,这本身会带来各种麻烦
  • 我需要set_transitions解决方法将方法用作操作

然而我对选项号的关注。 2是:

  • 它将状态与过渡分开,并与复杂的状态机分开,这将是非常混乱的
  • 我需要except TypeError:块来允许将静态方法用作操作

现在的问题是,哪种方式更可取? No1可读性可能更好吗?

也许我还没有看到另一个第三种选择?

提前感谢您的任何反馈!

/马丁

BTW这里是一个独立于两个选项的示例用法:

class Context(object):
    def __init__(self):
        self._state = StateA(self)

    def handle(self, msg):
        self._state = self._state(msg)

if __name__ == "__main__":
    CONTEXT = Context()
    CONTEXT.handle(MsgA())
    CONTEXT.handle(MsgB())
    CONTEXT.handle(MsgC())
    CONTEXT.handle(MsgB())

0 个答案:

没有答案