8

If I do the following:

a = range(9)

for i in a:
    print(i)

# Must be exhausted by now
for i in a:
    print(i)

# It starts over!

Python's generators, after raising StopIteration, normally stop looping. How then is range producing this pattern - it restarts after every iteration.

5
  • 1
    Have you read the documentation? Commented Dec 16, 2014 at 9:18
  • 1
    In short: the for i in a construct is generating a separate iterable each time... Commented Dec 16, 2014 at 9:20
  • 2
    What made you think range() is an iterator? (Generators are a specialised form of iterators, it is iterators that raise StopIteration). Commented Dec 16, 2014 at 9:31
  • 1
    Please excuse my not knowing the difference between the two. Part of the reason why I thought that way was because range being instantiated, like a=range(9), is very much similar to how a generator is instantiated in order to get an iterator. My mistake. Commented Dec 16, 2014 at 10:15
  • @jonrsharpe I did, but couldn't find what I was looking for. Perhaps I should learn how to read the docs first! Commented Dec 16, 2014 at 10:18

3 Answers 3

13

As has been stated by others, range is not a generator, but sequence type (like list) that makes it an iterable which is NOT the same as an iterator.

The differences between iterable, iterator and generator are subtle (at least for someone new to python).

  • An iterator provides a __next__ method and can be exhausted, thus raising StopIteration.

  • An iterable is a object that provides an iterator over its content. Whenever its __iter__ method is called it returns a NEW iterator object, thus you can (indirectly) iterate over it multiple times.

  • A generator is a function that returns an iterator, which of cause can be exhausted.

  • Also good to know is, that the for loop automatically queries the iterator of any iterable. Which is why you can write for x in iterable instead of for x in iter(iterable) which in turn is the preferred way to call for x in iterable.__iter__() .

All of that IS in the documentation, but IMHO somewhat difficult to find. The best starting point is probably the Glossary.

Sign up to request clarification or add additional context in comments.

Comments

4

range is a kind of immutable sequence type. Iterating it does not exhaust it.

>>> a = iter(range(9))  # explicitly convert to iterator
>>> 
>>> for i in a:
...     print(i)
... 
0
1
2
3
4
5
6
7
8
>>> for i in a:
...     print(i)
... 
>>> 

Comments

3

range is not a generator, it's a sequence type, like strings or lists.

So

for i in range(4):

is no different than

for i in "abcd":

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.