[Tutor] Skipping elements from inside generator loops

Scot W. Stevenson scot@possum.in-berlin.de
Thu, 1 Aug 2002 11:15:15 +0200


Hello there, 

So here I am playing around with generators, and just for the heck of it I 
see if I can get a for-loop to skip one element from inside the loop. To 
my surprise, this works (in Python 2.2):

==================================================
from __future__ import generators

procession= ['black cat',
             'white cat',
             'grey cat',
             'ALARM!',
             'the evil dog',
             'fat cat',
             'slow cat']

def animal_walk(animal_list):
    for one_animal in animal_list:
        yield one_animal

cat_parade = animal_walk(procession)

for animal in cat_parade:
    if animal == 'ALARM!':
        # Skip one animal on list
        cat_parade.next()
    else:
        print animal
=============================================

This produces:

===================
black cat
white cat
grey cat
fat cat
slow cat
===================

Somehow, it doesn't seem right to be able to change what amounts to a loop 
counter from the inside, even though it is useful here. Fooling around 
some more, I find that you can not do this with "normal" for loops:

===============================
for a in range(len(procession)):
    if procession[a] == 'ALARM!':
        a = a+1
    else:
        print procession[a]
===============================

lets fido into the fun (in other words, ignores the 'a=a+1'. It only works 
with a while-loop and a counter:

===============================
counter = 0
while counter < len(procession):
    if procession[counter] == 'ALARM!':
        counter = counter+2
    else:
        print procession[counter]
        counter = counter+1
===============================

Now I'm curious: Is this ability to manipulate generator loops from the 
inside considered a bug or a feature? It certainly makes the "normal" for 
loop behave differently than the generator for loop, and that alone seems 
like a good way to shoot yourself in the foot...

[While we're at it: I assume that there is a way to solve the problem with 
list comprehensions, but I can't figure it out. Note that looking for the 
dog directly is considered cheating: All you get to do is skip one list 
entry when somebody sounds the alarm.]

Thanks again for the help,
Y, Scot

Who is off to feed his own cat

-- 
  Scot W. Stevenson -- scot@possum.in-berlin.de -- Zepernick, Germany