List as FIFO in for loop

malkarouri malkarouri at gmail.com
Sat Mar 8 11:20:24 EST 2008


On Mar 8, 3:52 pm, duncan smith <buzz... at urubu.freeserve.co.uk> wrote:
> malkarouri wrote:
> > Hi everyone,
>
> > I have an algorithm in which I need to use a loop over a queue on
> > which I push values within the loop, sort of:
>
> > while not(q.empty()):
> >     x = q.get()
> >     #process x to get zero or more y's
> >     #for each y:
> >     q.put(y)
>
> > The easiest thing I can do is use a list as a queue and a normal for
> > loop:
>
> > q = [a, b, c]
>
> > for x in q:
> >     #process x to get zero or more y's
> >     q.append(y)
>
> > It makes me feel kind of uncomfortable, though it seems to work. The
> > question is: is it guaranteed to work, or does Python expect that you
> > wouldn't change the list in the loop?
>
> I have used exactly the same approach.  I think it's a clean (even
> elegant) solution.  I'd be surprised if it ceased to work in some future
> implementation of Python, but I don't know if that's absolutely guaranteed.
>
> Duncan

Thanks Duncan, I think I will go ahead and use it. Though the Python
tutorial says otherwise in section 4.2:
"It is not safe to modify the sequence being iterated over in the loop
(this can only happen for mutable sequence types, such as lists). If
you need to modify the list you are iterating over (for example, to
duplicate selected items) you must iterate over a copy.".

More explicitly, in 7.3 of the Python Reference Manual:
"Warning: There is a subtlety when the sequence is being modified by
the loop (this can only occur for mutable sequences, i.e. lists). An
internal counter is used to keep track of which item is used next, and
this is incremented on each iteration. When this counter has reached
the length of the sequence the loop terminates. This means that if the
suite deletes the current (or a previous) item from the sequence, the
next item will be skipped (since it gets the index of the current item
which has already been treated). Likewise, if the suite inserts an
item in the sequence before the current item, the current item will be
treated again the next time through the loop."
This can be interpreted as don't play with the past. However, the part
"When this counter has reached the length of the sequence the loop
terminates." is interpretable as either the starting sequence length
or the running sequence length.

Testing:

In [89]: x=range(4)

In [90]: for i in x:
   ....:     print i
   ....:     x.append(i+4)
   ....:     if i>=8:break
   ....:
   ....:
0
1
2
3
4
5
6
7
8

So it is the running sequence length. But I am still not sure if that
is guaranteed.

Regards,

Muhammad Alkarouri



More information about the Python-list mailing list