[Python-ideas] sentinel_exception argument to `iter`

Terry Reedy tjreedy at udel.edu
Sat Feb 8 09:32:56 CET 2014


On 2/7/2014 9:28 AM, Serhiy Storchaka wrote:
> 07.02.14 10:36, Terry Reedy написав(ла):
>> I wrote the above with the idea that there would be a third parameter to
>> provide an exception. It would have to have a private default like
>>
>> class _NoException(Exception): pass
>
> Natural default is StopIteration or ().

That does not work because iter has to know if the user called iter with 
only one argument, an iterable, or with two or (with the proposal) 
three, with the first argument being a callable.

def iter(iter_or_call, sentinel=<private object>, stop_iter=<private 
exception>):
   if sentinel == <private object> and stop_iter == <private exception>:
     # iter_or_call must be an iterable
     <do what iter(iterable) does now,
      which is to return iterable.__iter__()
      or getitem_iterable(iterable)>
   else:
     # iter_or_call must be a callable
     return callable_iterator(iter_or_call, sentinel, stop_iter)

where callable_iterator has been modified to take the third parameter 
and raise StopIteration if iter_or_call raises stop_iter.

class Callable_iterator:
   def __next__(self):
     try:
       val = self.func()
     except self.stop_iter:
       raise StopIteration from None
     if self.sentinel == value:
       raise StopIteration
     else:
       return val

If a user passes sentinel but not stop_iter, the except clause should 
have no effect and the method should work as it does currently. A 
default of StopIteration would accomplish that but it does not work for 
the iter switch. A private exception class also works since no exception 
raised by self.func should be an instance of such a class (unless the 
user violates convention).

If a user passes stop_iter but not sentinel, the if clause should have 
no effect and the iteration should continue until there is an exception. 
So the default sentinel should never compare equal to any value returned 
by self.func. A private instance of object on the left of == will invoke 
object.__eq__ which compares by identity. Unless a user violates 
convention by extracting and using the private instance, the function 
will never return it. Since value could compare equal to everything, the 
order for == matters.

-- 
Terry Jan Reedy




More information about the Python-ideas mailing list