Why Is The Range Object "not An Iterator"?
Solution 1:
The range object is iterable. However, it's not an iterator.
To get an iterator, you need to call iter() first:
>>>r=range(5,15)>>>next(iter(r))
5
>>>next(iter(r))
5
>>>next(iter(r))
5
>>>next(iter(r))
5
>>>i=iter(r)>>>next(i)
5
>>>next(i)
6
>>>next(i)
7
>>>next(i)
8
>>>iter(r)
<range_iterator object at 0x10b0f0630>
>>>iter(r)
<range_iterator object at 0x10b0f0750>
>>>iter(r)
<range_iterator object at 0x10b0f0c30>
Edit: But be careful not to call iter() with every call to next(). It creates a new iterator at index 0.
Solution 2:
range returns an iterable, not an iterator. It can make iterators when iteration is necessary. It is not a generator.
A generator expression evaluates to an iterator (and hence an iterable as well).
Solution 3:
The next builtin calls the __next__ hook method. So, range objects have a well defined __iter__, but not a well-defined __next__.
iterable objects have __iter__ defined, iterator objects have well defined __next__ (typically with an __iter__ method which simply returns self).
Solution 4:
It's because the next function calls the next method of the object that passed in.
next(...)
x.next() -> the next value, or raise StopIteration
listiterators and generators both have the next method.
>>> iter(range(1)).__class__.next
<slot wrapper 'next' of 'listiterator' objects>
>>> iter(x for x inrange(1)).__class__.next
<slot wrapper 'next' of 'generator' objects>
But a list doesn't have it. And that is the reason why it raises that exception.
>>> list.next
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: typeobject'list' has no attribute 'next'next doesn't care much about whether the object it's passed is an iterator or not.
>>>classFoo():...defnext(self):...return"foo"...>>>foo = Foo()>>>next(foo)
'foo'
>>>next(foo)
'foo'
But adding the next method doesn't necessarily make it a collection/sequence/iterable.
>>>classFoo():...defnext(self):...return"Foo">>>[x for x in Foo()]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: iteration over non-sequence
>>>iter(Foo())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: iteration over non-sequence
But adding the __iter__ method to it makes it one.
>>>classFoo():...defnext(self):...return"Foo"...def__iter__(self): return self...>>>[x for x in Foo()]
^CTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyboardInterrupt
>>>iter(Foo())
<__main__.Foo instance at 0x7fd77307c488>
The next seems to have some builtin intelligence when it comes to list.
>>>classFoo():...pass...>>>foo = Foo()>>>next(foo)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: instance has no next() method
>>>next(range(20))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator
Post a Comment for "Why Is The Range Object "not An Iterator"?"