python - Detecting that an object is repeatedly iterable -
does obj == iter(obj)
imply obj
isn't repeatedly iterable , vice versa? didn't see such wording in docs, according this comment, standard library checks if object repeatedly iterable by testing if iter(obj) obj
:
@agf: there parts of python standard library rely on part of spec; they detect whether iterator/generator testing
if iter(obj) obj:
, because true iterator/generator object have__iter__
defined identity function. if test true, convertlist
allow repeated iteration, otherwise, it's assumed object repeatably iterable, , can use is.
– shadowranger jun 3 @ 17:23
the docs state if obj
iterator, it's required iter(obj)
returns obj
. don't think that's enough conclude non-repeatedly iterable objects can identified using iter(obj) obj
.
all iterators iterables, not iterables iterators.
the requirement of iterable defines __iter__()
method returns iterator:
one method needs defined container objects provide iteration support:
container.__iter__()
return iterator object.
an iterator must follow iterator protocol, has 2 requirements:
it has
__iter__()
method that returns object itself:iterator.__iter__()
return iterator object itself.it has
__next__()
method returns next item on each call, and, once exhausted, raisesstopiteration
on every subsequent call:once iterator’s
__next__()
method raisesstopiteration
, must continue on subsequent calls. implementations not obey property deemed broken.
these requirements mean iterators never repeatable, , can confirm iterable iterator (and therefore unrepeatable definition) confirming iter(obj) obj
true
:
def is_unrepeatable(obj): return iter(obj) obj
however: since requirement of iterable iter(obj)
returns some iterator, can't prove is repeatable. iterable define __iter__()
method returns iterator different behaviour each time it's called: instance, return iterator iterates on elements first time it's called, on subsequent calls, return iterator raises stopiteration
.
this behaviour strange (and annoying), not prohibited. here's example of non-repeatable iterable class not iterator:
class unrepeatable: def __init__(self, iterable): self.iterable = iterable self.exhausted = false def __iter__(self): if self.exhausted: return else: self.exhausted = true yield self.iterable
>>> x = unrepeatable([1,2,3]) >>> list(x) [1, 2, 3] >>> list(x) [] >>> iter(x) x false >>>
i wouldn't hesitate call such "fake iterator" badly-behaved, , can't think of situation you'd find 1 in wild, demonstrated above, possible.
Comments
Post a Comment