Home > Article > Backend Development > Does range in python3 return an iterator?
What does the range of Pyhton3 return? Many people will say without thinking that this is not simple. In Python 2, range() will return a list. In Python 3, range has been replaced by xrange, and an iterator (Iterator) is returned.
Congratulations, you got the wrong answer.
range() returns an Iterable, not an Iterator.
a Python 3.6.3 (default, Nov 3 2017, 14:41:25) Type 'copyright', 'credits' or 'license' for more information IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: a = range(10) In [2]: a Out[2]: range(0, 10) In [3]: import collections In [4]: isinstance(a, collections.Iterable) Out[4]: True In [5]: isinstance(a, collections.Iterator) Out[5]: False
The principle is very simple, let’s briefly talk about it first Iterable and Iterator, don't try to compare the two, because they are fundamentally different concepts. The literal meaning of both is very clear: Iterable is an iterable object, and calling iter(Iterable) on it will get an iterator; while Iterator is an iterator, and calling next(Iterator) on it will get the next element. .
Python advocates protocols, which to put it bluntly are duck types. If you implement __iter__(), (that is, you can get an Iterator by calling iter()), then you are an Iterable; if you implement __next__() and __iter__(), you are an Iterator.
Wait a minute, doesn’t Iterator just call next() to get the next element? Why does Iterator also need to implement Iterable's __iter__() method? This is not pure!
Why does Python's Iterator implement __iter__() (the usual implementation is return self). The official documentation says it quite clearly.
Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted.
A simple translation means that Iterator also requires the implementation of __iter__(), because the parameter received in many places is an Iterable. If all Iterators are Iterable, then these Iterable places can be used without any obstacles. Use Iterator. For example, let’s take a for loop. Regarding the for loop, I found this description in Python’s wiki (which is quite old):
Basically, any object with an iterable method can be used in a for loop. Even strings, despite not having an iterable method – but we’ll not get on to that here.
That is, the for loop gets an Iterable Iterator, and then uses this Iterator to perform Iterate. If Iterator implements the __iter__() method, then the for loop can iterate over Iterator without any hindrance, Neat! Imagine that Python's generator is also an Iterator. If the for loop cannot support iteration of Iterator, life would be worse than death.
So there is such an "excessive" requirement for Iterator. We can think that all Iterators are Iterable. So back to the original question, why does range() return an Iterable instead of an Iterator?
Considering that we usually use range(), we think it is a container that represents a range. You can use this container to initialize other containers without any problems.
>>> numbers = range(3) >>> tuple(numbers) (0, 1, 2) >>> tuple(numbers) (0, 1, 2)
If range() returns an iterator, then the above seemingly normal code is in trouble:
>>> numbers = iter(range(3)) >>> tuple(numbers) (0, 1, 2) >>> tuple(numbers) ()
Summary
Iterator is stateful and can only be traversed once. It is "consumption type" and cannot be "consumed twice". Iterable is stateless (not too rigorous here, let alone the Iterable of Iterator). Every time iter() is called on Iterable, a new iterator will be obtained.
The above is the detailed content of Does range in python3 return an iterator?. For more information, please follow other related articles on the PHP Chinese website!