On Thu, Oct 01, 2015 at 11:29:51AM -0700, Chris Barker wrote:
On Thu, Oct 1, 2015 at 8:10 AM, Steven D'Aprano firstname.lastname@example.org wrote:
But there is a *general* distinction between two cases:
- iterables which are iterators
- iterables which are not iterators
We have a name for the first set: "iterators". But we don't have a name for the second set. Andrew suggested "non-iterator iterables" is too clumsy for general use, and suggests we need a better name. You suggested "iterables", but that clearly cannot work, since iterators are a kind of iterable.
sure -- but I've lost track of why it matters. "iterator" is well defined. And so is "iterable" -- why do we need to care whether the iterable returns itself when asked for an iterator?
In and of itself, it probably isn't, except as a short-cut for deciding whether something is an iterator.
But if why do you need to know that something is an iterable, but NOT an iterator? isn't that an implementation detail?
I forget the original context -- I think it was Andrew who first mentioned this. Possibly over confusion about (x)range.
But in general, it's important because:
- iterators are not random access, other iterables typically are;
- iterators are one-shot (cannot be restarted), other iterables are typically re-runnable.
This makes a difference. Just a few days ago, somebody mis-reported a supposed "bug" in all() and any(). For example:
values = (x%5 == 3 for x in range(8)) print(list(values)) print(all(values)) # should return False
Obvious error is obvious: having printed out the values from the generator expression, values is now exhausted, and all() of the empty set is True (vacuous truth). The difference between general iterables which may or may not be one-shot iterators, and those which are definitely not iterators, is not always just an implementation detail.