Is an iterator also an iterable?
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Over Ancient Waters Looping
--
Chapters
00:00 Is An Iterator Also An Iterable?
00:26 Answer 1 Score 7
01:39 Accepted Answer Score 19
03:42 Answer 3 Score 1
04:20 Answer 4 Score 0
04:40 Thank you
--
Full question
https://stackoverflow.com/questions/4610...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #python3x #methods #iterator #iterable
#avk47
ACCEPTED ANSWER
Score 19
An iterable needs to implement an __iter__ method or a __getitem__ method:
An object can be iterated over with
forif it implements__iter__()or__getitem__().
An iterator needs a __iter__ method (that returns self) and a __next__ method (I'm not 100% sure about the __next__).
it is true that an iterator always has __iter__ method?
Yes!
This is also documented in the Data model:
object.__iter__(self)This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container.
Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see Iterator Types.
(Emphasis mine)
As to your second question:
Is an iterator also an iterable?
Yes, because it has a __iter__ method.
Additional notes
Besides the formal implementation it's easy to check if something is iterable by just checking if iter() can be called on it:
def is_iterable(something):
try:
iter(something)
except TypeError:
return False
else:
return True
Likewise it's possible to check if something is an iterator by checking if iter() called on something returns itself:
def is_iterator(something):
try:
return iter(something) is something # it needs to return itself to be an iterator
except TypeError:
return False
But don't use them in development code, these are just for "visualization". Mostly you just iterator over something using for ... in ... or if you need an iterator you use iterator = iter(...) and then process the iterator by calling next(iterator) until it throws a StopIteration.
ANSWER 2
Score 7
An iterator is iterable. And yes, an iterator always has an __iter__ method.
Calling iter on an iterator, which summons the __iter__ hook, returns the same iterator:
>>> it = iter([]) # return iterator from iterable
>>> it is iter(iter(it)) is it.__iter__().__iter__().__iter__()
True
A classical example of method chaining.
As you must have also noticed, most implementations of the iterator protocol for custom classes always follows:
def __iter__(self):
return self
That is if the iteration is not delegated to another iterator, via say return iter(...).
It would be quite counter-intuitive for an iterator to not implement the iterator protocol don't you think? The __iter__ implementation of the protocol is described below:
iterator.__iter__()Return the iterator object itself. This is required to allow both containers and iterators to be used with the
forandinstatements.
[Emphasis mine]
This behaviour is expectedly consistent with iterator objects returned by builtins:
>>> m = map(None, [])
>>> m
<map object at 0x...>
>>> m is m.__iter__().__iter__().__iter__()
True
P.S: I apologise for calling dunders repeatedly; makes it look like it's the right thing to do. But it's not!
ANSWER 3
Score 1
An iterator is iterable.
That's documented and explained here:
Iterators are required to have an
__iter__()method that returns the iterator object itself so every iterator is also iterable
An iterable is not necessarily an iterator
Iterators must have a __next__ method, by definition. To give a simple counterexample:
>>> ''.__next__
AttributeError: 'str' object has no attribute '__next__'
A string object is an iterable, but is not an iterator.
ANSWER 4
Score 0
Does an iterator always have the __iter__ method?
Yes. All iterators have an __iter__ method that returns itself. From the docs
iterator.__iter__()Return the iterator object itself. This is required to allow both containers and iterators to be used with the for and in statements.