Strange range

Steven D'Aprano steve at pearwood.info
Sat Apr 2 06:09:53 EDT 2016


On Sat, 2 Apr 2016 07:14 am, Marko Rauhamaa wrote:

> There's a bit of a cognitive dissonance between iterables and iterators.
> On the one hand, they behave identically in many contexts. On the other
> hand, the distinction is crucial in some special cases.

Iterable just means "something which can be iterated over". Anything which
you can feed directly into a for-loop:

for x in obj: ...

is by definition an iterable. The particular mechanism by which iteration is
performed is unspecified.

In Python today, there are two specific mechanisms, although in practice
only one commonly is used. The older of the two is the "Sequence Protocol",
which says that iteration is performed by repeatedly fetching an item from
the object with an incrementing index until IndexError is raised:

x = obj[0]
x = obj[1]
x = obj[2]
...


The newer, and more common, mechanism is to call iter(obj) to get an
iterator, then repeatedly call next(iterator) until it raises
StopIteration.

it = iter(obj)
x = next(it)
x = next(it)
x = next(it)
...


So what's an iterator? Any object which obeys the "Iterator Protocol". The
rules for the protocol are:

- the object must provide two methods, __iter__ and __next__;

- __iter__ must return self;

- __next__ must return the next value in the sequence, 
  or raise StopIteration.


range objects themselves do not obey the iterator protocol, which makes them
not iterators:

py> o = range(23)
py> iter(o) is o
False
py> hasattr(o, '__next__')
False


But they are *iterable* since you can call iter on a range object and get an
iterator:

py> it = iter(o)
py> iter(it) is it
True
py> hasattr(it, '__next__')
True



> (Somehow, the difference between iterables and iterators is analogous
> with the difference between C's arrays and pointers.)

I don't understand this analogy. Can you explain please?


-- 
Steven




More information about the Python-list mailing list