Why emumerated list is empty on 2nd round of print?

Oscar Benjamin oscar.j.benjamin at gmail.com
Fri Sep 7 14:33:39 EDT 2018


On Fri, 7 Sep 2018 at 16:25, Schachner, Joseph
<Joseph.Schachner at teledyne.com> wrote:
>...
> Now, on to the second part: the problem you showed - that you can only loop through aList:print(i,j) once - is BECAUSE you hung onto it from one loop to another.  Once the iterator is exhausted, it's exhausted.
>
> Think of another more common iterator you've probably used:  file = open("filename.txt")         for line in file;                print line
> On EOF the iterator throws an exception (that is expected), the for loop catches the exception and exits.
> Files can be "rewound" by file.seek(0).  But other than that, once you have reached EOF, you have reached EOF.  It doesn't automagically rewind.  If you do another     for line in file;  print line      it will not print anything.  Exactly the same behavior as you are surprised about for the enumerate iterator.
>
> I don’t even know if there is a method to reset the enumerate iterator.  If there isn't one, then you should not hold the iterator from one loop to the next, you have to make another one.

There is no way to reset the enumerate iterator because it would not
be possible in general. You can use enumerate with any iterable
including an iterator that cannot itself be reset:

for lineno, line in enumerate(fileobj, 1):
    print(lineno, line)

In this case enumerate cannot reset the fileobj iterator there would
be no way to implement enumerate such that it is always resettable.
(Even if enumerate knew it was a file object that wouldn't necessarily
make it seekable e.g. if it was a FIFO).

You *could* however have enumerate return an object that was
re-iterable whenever its underlying iterable is (but that's not how it
is designed):

class enumerate:
    def __init__(self, iterable, start=0):
        self.iterable = iterable
        self.start = start
    def __iter__(self):
        count = self.start
        for val in self.iterable: # Implicitly calls iter on iterable again
            yield count, val
            count += 1

--
Oscar



More information about the Python-list mailing list