Incrementing a string -- puzzing "solution"...

Terry Reedy tjreedy at udel.edu
Thu Sep 16 21:13:50 EDT 2004


"Pierre Fortin" <pfortin at pfortin.com> wrote in message 
news:20040916004438.657b50a4 at gypsy.pfortin.com...
> On Wed, 15 Sep 2004 15:08:20 -0700 John wrote:
> Puzzling...  I hacked at this problem as a flexibility learning exercise
> and actually got this to work; but... does 'while True' in a generator
> have side-effects...??

No.  Note that the 'while True' and the rest of the body code end up in/as 
the body of the .next method of the generator object produced by calling 
the generator function.  You don't have to understand all this to use 
generators in for statements, but you should when using them with while 
loops.

>  Or generator recursion?

I has a main of sometimes simplifying variable depth recursion ;-)

> I don't see how the string actually _grows_ inside  the while....  :^?
> I was just expecting the prefix to be '', then 'a'...'z' giving a..z,
> aa..az, ba..bz, ... za..zz -- not continuing through aaa...azz and
> onwards... It's cool; but boggles my mind at the moment...  not that
> that's a stretch...  :^)

The following is an never-ending generator, with unbounded levels of 
recursion.  The generator on each level of recursion is the same and 
therefore generates the same sequence.  Each is 'behind' the level above it 
and 'ahead' of the level beneath (counting the first as the top level) in 
terms of where it is in the sequence.

Prefix grows from length 0 to 1 on the first call to the next method of the 
level beneath it.  That same call causes the creation of another 'instance' 
(still inactive) two levels down.  When a later g.next call causes the 
prefix one level down to grow from 0 to 1, the prefix as the current level 
grows from 1 to 2.  And so on.  At any time (except transitions), there is 
a stack of n+1 identical instances of the generator (and its .next methods) 
with prefixes ranging from length n-1 down to 0 with the bottom instance 
having no prefix at all.

> def ascinc(start='a',end='z'):
>    g = ascinc(start,end)

This creates a new generator object but does NOT call its .next method.

>    prefix = ''
>    while True:
>        for i in range(ord(start[-1]),ord(end[-1])+1):
>            yield (prefix + chr(i))
>        prefix = g.next()

Increments in prefix length bubble up from the bott

> g = ascinc('a')

This 'kickstarts' the process by creating the top generator without calling 
it.

> for i in range(100):
>    print g.next(),

while True: print g.next() # would theorectically continue indefinitely, as 
would
for s in ascinc('a'): print s # both would croak on the recursion limit

In each case, the first call of .next() causes creation of a second 
generator and a blank prefix.  I hope the mechanism is now clearer for you.

Terry J. Reedy






More information about the Python-list mailing list