[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: