Question about exausted iterators
Terry Reedy
tjreedy at udel.edu
Wed May 17 14:44:57 EDT 2006
"Christophe" <chris.cavalaria at free.fr> wrote in message
news:446b48e2$0$5293$626a54ce at news.free.fr...
> Is there a good reason why when you try to take an element from an
> already exausted iterator, it throws StopIteration instead of some other
> exception ?
Yes.
.
.
To distinguish the control message "I am done yielding values, as per the
code specification (so don't bother calling me again)." from error messages
that say "Something is wrong, I cannot yield values and give up." In other
words, to distinguish expected correct behavior from unexpected incorrect
behavior. This is essential for the normal and correct use of iterators.
> I've lost quite some times already because I was using a lot
> of iterators and I forgot that that specific function parameter was one.
I think you mean 'specific function argument' for a parameter which could
be any iterable.
> Exemple :
Example
> >>> def f(i):
> ... print list(i)
> ... print list(i)
> ...
> >>> f(iter(range(2)))
> [0, 1]
> []
As per specification.
I am guessing that you want the first list() call to terminate normally and
return a list, which requires exhausted i to raise StopIteration, while you
want the second list() to not terminate but raise an exception, which
requires exhausted i to raise something other than StopIteration. Tough.
One solution is call list(i) exactly once:
def f(i):
li = list(i)
print li
print li
Another is to document f as requiring that i be a non-iterator reiterable
iterable and only pass correct arguments.
A third is to add a line like
if iter(i) is i: raise TypeError("input appears to be iterator")
This is not quite exact since it will improperly exclude self-iterator
reiterables (which, I believe, no builtin is) and improperly pass
non-reiterable non-iterator iterables (at least some file objects). But it
might work for all your cases.
Terry Jan Reedy
More information about the Python-list
mailing list