Weird generator id() behaviour (was Re: Python code written in1998, howto improve/change it?)

Bengt Richter bokr at oz.net
Wed Jan 25 14:13:13 CET 2006


On Wed, 25 Jan 2006 12:33:17 +1300, Carl Cerecke <cdc at maxnet.co.nz> wrote:

>Adding a continue statemtent after the yield statements yields :-) a 
>speed increase. Still not as good as functions though. (about 30% slower)
>
>Cheers,
>Carl
>
>Carl Cerecke wrote:
>> Carl Cerecke wrote:
>> Generator FSM done properly (well, better anyway). They are still almost 
>> twice as slow as plain function calls, though.
>> 
<snip>
I think I would use a generator to do state transitions, but make the state
external, or at least the part that's interesting to the outside world.

In this peculiar example the transition rules are the same for both states,
so you only need one implementation of the logic. So the example is not so nice.


 >>> def fsm(state, events):
 ...     for action in events:
 ...         if action == 'lift': state.name = 'ON'
 ...         elif action == 'push': state.name = 'OFF'
 ...         else:
 ...             state.name = 'END'
 ...             break
 ...         yield state
 ...
 >>> def actions(n):
 ...     import random
 ...     return iter([random.choice(['lift','push']) for i in range(n-1)] + [None])
 ...
 >>> class State(object): pass
 ...
 >>> def test(r=1000000):
 ...     state = State()
 ...     state.name = 'ON'
 ...     from time import clock
 ...     t0 = clock()
 ...     for state in fsm(state, actions(r)): pass
 ...     t1 = clock()
 ...     print '%12.6f'%((t1-t0)/r)
 ...
 >>> test(1000)
     0.000058
 >>> test(1000)
     0.000032
 >>> test(1000)
     0.000032
 >>> test(100000)
     0.000032
 >>> a = list(actions(10))
 >>> a
 ['lift', 'push', 'push', 'lift', 'push', 'lift', 'push', 'lift', 'lift', None]
 >>> state = State()
 >>> state.name = 'START'
 >>> f = fsm(state, a)
 >>> for state in f: print state.name,
 ...
 ON OFF OFF ON OFF ON OFF ON ON
 >>>
 
Obviously you can keep state in the fsm generator by placing yields in different places and
looping in different ways, but always storing the externally interesting state as attributes
of the state parameter and yielding that to tell the world the latest. Since only attributes
are being modified, the original state binding could be used and the generator's yielded
value could be ignored, but it could be handy if the generator is passed around IWT.

The world could also feed info in as attributes of state. And other generators could share
the same external state variable and all kinds of weird things could be built ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list