Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling multiple iterators on xrange objects

Why does

zip(*[xrange(5)]*2)

give [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] but

zip(*[iter(xrange(5))]*2)

give [(0, 1), (2, 3)]?

I always though that generator were iterators, so iter on a generator was a no-op.

For example,

list(iter(xrange(5)))
[0, 1, 2, 3, 4]

is the same as

list(xrange(5))
[0, 1, 2, 3, 4]

(The same is true for Python 3, but with list(zip( and range.)

like image 310
Paul Draper Avatar asked Dec 18 '13 23:12

Paul Draper


1 Answers

Theres a difference between an iterable and an iterator. You can use iter(x) to build an iterator for any given iterable x. An iterator encapsulates the state of an iteration, while an iterable is something you can create a new iterator from.

xrange() is an iterable, but not an iterator. You can create multiple iterators for a single xrange() object, and each of it has its own position.

The zip() function implicitly calls iter() on each of its arguments. For zip(*[xrange(5)]*2), this will create two iterators for the same xrange() objects, each with its own iteration state. For zip(*[iter(xrange(5))]*2), you are already passing in the same iterator twice. Calling iter() on an iterator simply returns the iterator itself, so that you end up with only a single iterator in this case.

like image 121
Sven Marnach Avatar answered Sep 30 '22 01:09

Sven Marnach