Weird generator id() behaviour (was Re: Python code written in 1998, how to improve/change it?)
Carl Cerecke
cdc at maxnet.co.nz
Tue Jan 24 15:19:26 EST 2006
Wolfgang Keller wrote:
> On Fri, 20 Jan 2006 05:16:57 +0100, Peter Hansen wrote
> (in article <mailman.821.1137730663.27775.python-list at python.org>):
>
>
>>I believe the more modern approach to this is to use generators in some
>>way, yield each other as the next state. This way you avoid all almost
>>all the function call overhead (the part that takes significant time,
>>which is setting up the stack frame) and don't have to resort to
>>bytecode hacks for better performance.
>
>
> Dumb question from a endless newbie scripting dilettant:
>
> Do you have a reference to a cookbook example for this method?
It turns out that generators are more efficient than the eval function
excuting bits of compiled code. About 20-25% faster.
However, the generators exhibit some weird behaviour.
The included code shows an example using a compile/eval FSM method, and
a generator method. Note, in particular, the pattern of ids of the
generator objects. I had expected some complications in the ids, but not
a repeatable sequence of length 3 after the first generator object.
What is going on? Anybody?
#!/usr/bin/env python
import time
s_on = compile('''
print 'on'
action = next_action()
if action == 'lift':
state = s_on
elif action == 'push':
state = s_off
else:
state = None
''','','exec')
s_off = compile('''
print 'off'
action = next_action()
if action == 'lift':
state = s_on
elif action == 'push':
state = s_off
else:
state = None
''','','exec')
def g_on():
print "on"
action = next_action()
if action == 'lift':
yield g_on()
elif action == 'push':
yield g_off()
else:
yield None
def g_off():
print "off"
action = next_action()
if action == 'lift':
yield g_on()
elif action == 'push':
yield g_off()
else:
yield None
def actions(n):
import random
for i in range(n-1):
yield random.choice(['lift','push'])
yield None
#r = 1000000
r = 10
next_action = actions(r).next
#a = time.clock()
while next_action():
pass
#z = time.clock()
#print "action generator:",z-a
next_action = actions(r).next
#print "---"
state = s_on # start state
#a = time.clock()
while state:
eval(state)
#z = time.clock()
#print z-a
print "---"
next_action = actions(r).next
s_g_on = g_on()
s_g_off = g_off()
state = s_g_on
#a = time.clock()
while state:
print id(state)
state = state.next()
#z = time.clock()
#print z-a
#Cheers,
#Carl.
More information about the Python-list
mailing list