state machine and a global variable

Chris Mellon arkanes at gmail.com
Fri Dec 14 18:02:29 EST 2007


On Dec 14, 2007 4:43 PM,  <tuom.larsen at gmail.com> wrote:
> On Dec 14, 11:06 pm, Bruno Desthuilliers
> <bdesth.quelquech... at free.quelquepart.fr> wrote:
> > tuom.lar... at gmail.com a écrit :
>
> >
> > > Dear list,
> > > I'm writing very simple state machine library, like this:
> >
> > > _state = None
> >
> > > def set_state(state):
> > >     global _state
> > >     _state = state
> >
> > > def get_state():
> > >     print _surface
> >
> > NameError here !-)
> >
> >
> >
> > > but I hate to use global variable.
> >
> > <aol />
> >
> > > So, please, is there a better way
> > > of doing this? All I want is that a user has to type as little as
> > > possible, like:
> >
> > > from state_machine import *
> > > set_state(3)
> > > get_state()
> >
> > > I.e., nothing like:
> > > import state_machine
> > > my_machine = state_machine.new_machine()
> > > my_machine.set_state(3)
> > > my_machine.get_state()
> >
> > A possible solution:
> >
> > # state_machine.py
> > class _StateMachine(object):
> >    def __init__(self):
> >      self._state = SomethingHere()
> >    def get_state(self):
> >      return self._state
> >    def set_state(self, xxx):
> >      # etc
> >
> > _s = _StateMachine()
> > get_state = _s.get_state()
> > set_state = _s.set_state()
> >
>
> I guess you meant without the parentheses:
> get_state = _s.get_state
> set_state = _s.set_state
>
>
> > You still have a global, but at least it's a machine instance, not it's
> > state !-)
> >
> > Now the question is: why do you think it's so important for your users
> > to only see functions ? What's so wrong with:
> >
> > from state_machine import *
> > m = get_state_machine()
> > m.set_state(42)
>
> Well, I guess I can see the advantages of using the class instances
> but ... um ... the world isn't like that! :)
>
> Consider this: how do you add up some numbers?
> - "My sum is zero."
> - "I add 3 to my sum."
> - "I add 2 to my sum."
>
> Or:
> - "Three."
> - "plus two."
>
> Implicit context, some people call it. Sometimes it's useful to be as
> precise as possible ("explicit is better than implict", right?) but
> sometimes, it seems to me, it's just more natural not to repeat the
> context all over again.
>

You're way too hung up on context when you should be hung up on state.
Implicit state is bad, implicit global state is worse. You've got a
shared global state, with an interface that's designed to dispatch on
and mutate that state. It's basically every bad thing you can imagine
about global state. Using an object means that the state machine is
*local* state. Local state is good, because you've got a way to attach
a name to it, to manipulate it explicitly, and to pass it around to
other places.

Your example presupposes two different use cases anyway, but most
importantly what you're describing with sum is a mutation of local
state (a local name binding), which is a very different thing than
your state machine API.

Honestly, I can't even imagine why you would want to implement a state
machine *library* this way. If you meant "a library that has internal
state" it makes a little more sense - I use an approach kind of like
the one Bruno showed to handle global configuration and logging - but
if you meant "a library for implementing state machines" you're on
totally the wrong track.



More information about the Python-list mailing list