Help with coroutine-based state machines?

Carel Fellinger carel.fellinger at chello.nl
Thu May 29 18:08:58 EDT 2003


On Thu, May 29, 2003 at 04:10:02PM +0100, Alan Kennedy wrote:

... a lot of fine things snipped

> To do this, here is the little bit of hackery that I came up with:
> at __init__ time of the state-machine object, it modifies the
> instance dictionary, replacing generator-functions with their
> instantiated generator-iterators.
> 
> def __init__(self):
> 	statenames = ['state1', 'state2', 'state3', 'state4']
> 	for name in statenames:
> 		# Turn each generator-function into an instantiated
>                 # generator-iterator
> 		self.__dict__[name] = eval ('self.%s()' % name)

I don't see the hackery here, maybe you don't too:) if you replace
__dict__ and eval with get/setattr calls, like:

                setattr(self, name, getattr(self, name)())

see, it looks like ordinairy python code now:)

...
> Differentiating generator-functions from functions.
...
> question I'd like to ask: can anyone tell me how to discover the
> generator-functions of an object, and differentiate them from
> ordinary functions?

the simplest and best thing to do would be to distinguish them on name, like:

   all generator function names have to start with "g_"

you could also use the inspect module to get the source of each function
and look for "yield", or play with the code object, but how do you know
that every so found generator is ment to be used as a state-iterator,
could well be some kind of helper generator.

...
> working. Furthermore, it won't be possible to create a new
> generator-iterator, because we've overwritten the reference to the
> generator-function in the instance dictionary! Hmm, maybe that is
> too much a hack :-| Anyway.

Ah, I see why you thought it hackery, but be asured: you didn't:)
The generator-function is still there as a method in the class
dictionary, you merely shadowed it by binding the generator-iterator
to the same name in the instance of the class.

 
> The addition of the sentinel value for exiting or suspending the
> state machine means that we can now suspend and resume the machine
> at will. It can be suspended by yielding a "suspend" state (which

I haven't really thought it out, but couldn't you use an instance flag
for this and test on it instead of those "while 1:" loops?  besides...

...
> The "temporal locality" of the code (as opposed to the "spatial
> locality" of traditional code) greatly aids readability, and
> modifiability, IMHO. The code seems more natural, more

...right...

> And finally: infinite loops.
> ----------------------------
> 
> Another question I just thought of: Each of the state
> generator-functions must be wrapped inside an infinite while loop,
> so that the states never "run out of values". These while loops
> clutter the code somewhat, and it would be nice to not need them. I

...wrong:)  To me atleast, the presence of those infinite loops
highlights that were dealing with "temporary locality" here, so
I would leave them in.


-- 
groetjes, carel





More information about the Python-list mailing list