Re: Problems found while inspecting 2005->2007 debdiffs
Florent Rougon <f.rougon@free.fr> wrote:
> | 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
In fact, I think this index thing (the counter being an index in the
list) is out-of-date since we have iterators in Python.
When l is a list, and I do:
for e in l:
Python asks the list l for an iterable object (only once, at the
beginning of the loop). Let's call this object i. At the end of each
iteration, it calls i.next() to:
- check whether the loop should stop;
- get this object and assign it to e, if the loop can continue.
So, when we remove elements from l in the loop, there *is* an impact on
the iterator i: it can then only iterate on the remaining objects of l.
With this mechanism in mind for executing the loop, having i tied to l
is not really surprising for Python programmers (objects are usually
manipulated by reference, not by copy, so we're used to that).
This theory is somewhat[1] confirmed by the attached sample program,
where I make l a subclass of the 'list' type that prints a message when
its __iter__() method (the one that returns an iterator) is called.
#! /usr/bin/env python
import sys
class FloList(list):
def __iter__(self):
print "__iter__() is being called"
return list.__iter__(self)
def main():
l = FloList([0, 1, 2, 3, 4, 5, 6])
i = 0
for e in l:
if (i % 2) == 0:
l.remove(i)
print e
i += 1
sys.exit(0)
if __name__ == "__main__": main()
[1] Unless the list type is special-cased for loop execution, as
opposed to its subclasses...
--
Florent
Reply to: