On 9/29/2016 12:36 PM, MRAB wrote:
On 2016-09-29 16:56, Steve D'Aprano wrote:
On Thu, 29 Sep 2016 09:53 pm, MRAB wrote:
What if an _exhausted_ iterator was falsey?
Logic is about binary distinctions, rather than about 'truth'. For
non-buggy iterator it, the useful binary distinction is whether next(it)
returns an object, the truthy action, or raises StopIteration, the
falsey action. The for loop machinery converts this binary action
distinction into another binary action distinction: execute the suite
and call next again versus proceed to the else clause if there is one or
do nothing. In other words, for loops indeed treat an exhausted
iterator as falsey.
The problem is that in general you can't tell if an iterator is exhausted
until you attempt to advance it. So even if bool(iterator) returns True,
the call to next() may raise StopIteration:
[snip]
By "exhausted" I meant "has previously raised StopIteration".
The iterator protocol could have required that iterators have
'self._bval = True' in .__init__, method 'def __bool__(self): return
self._bval, and 'self._bval = False' in .__next__ just prior to 'raise
StopIteration'.
However, the iterator protocol is intentionally as simple as possible
and the extra baggage would nearly always be useless. If you use a
non-iterator iterable in a for statement, the temporary iterator is
discarded as soon as it raises StopIteration. If you pass an iterator
to a function that iterates, you likely created it on the fly as an
expression, and it will be discarded when the function returns. If you
do have a reference, you can (and perhaps should) delete it after the
function returns.
Still, if one has a specialized use-case for iterables with the extra
baggage, one can create them as instances of the following wrapper.
class BoolIter:
def __init__(self, iterable):
self._it = iter(iterable)
self._bval = True
def __iter__(self):
return self
def __bool__(self):
return self._bval
def __next__(self):
try:
return next(self._it)
except StopIteration:
self._bval = False
raise
--
Terry Jan Reedy
--
https://mail.python.org/mailman/listinfo/python-list