[Python-ideas] sentinel_exception argument to `iter`

Terry Reedy tjreedy at udel.edu
Sat Feb 8 08:32:27 CET 2014


On 2/7/2014 7:30 PM, Steven D'Aprano wrote:
> On Fri, Feb 07, 2014 at 04:54:04PM -0500, Terry Reedy wrote:
>> On 2/7/2014 3:39 AM, Steven D'Aprano wrote:

This

>>>    "the callable is called until it returns the sentinel, unless the
>>>     sentinel is an exception instance or class, in which case the
>>>     callable is called until it raises that exception, or one which is
>>>     compatible with it"
>>
>> To repeat, for the 3rd or 4th time, this is not the behavior that either
>> I or Ram proposed. I even provided code to be clear as to what I mean at
>> the time.

is critically different from what I actually wrote for how to change the 
one-line docstring summary

> You did write:
>
>      No new parameter is needed. We only need to add 'or raises' to the
>      two-parameter iter definition "In the second form, the callable is
>      called until it returns the sentinel." to get "In the second form,
>      the callable is called until it returns or raises the sentinel."

and the code that followed because it adds 'unless the sentinel is an 
exception instance or class'. Your addtion would change existing 
behavior before an exception is raised (if ever). I explicitly said in 
both code and text that I was not proposing to do that, but only to 
change what happened if and when an exception were raised (at which 
point there would be no more return values values to worry about.

> If you've changed your mind, I'll be glad to hear it,

As I already responded to you at 4:28 EST Friday, I withdrew my 
reuse-the-parameter proposal, in response to Yuri, 2 hours before the 
timestamp I have on your first response. In that response to you, I 
discussed in several paragraphs the actual existing parameter and how to 
add a third parameter. Since you did not read it, here it is again.

'''
In a later message, I reversed myself, in spite of the actual C 
signature making it a bit messy. Although help says 'iter(callable, 
sentinel)', the actual signature is iter(*args), with any attempt to 
pass an arg by keyword raising
TypeError: iter() takes no keyword arguments

Let n = len(args). Then the code switches as follows:
n=0: TypeError: iter expected at least 1 arguments, got 0
n>2: TypeError: iter expected at most 2 arguments, got 3
n=1: Return __iter__ or __getitem__ wrapper.
n=2: if callable(args[0]): return callable_iterator(*args),
      else: TypeError: iter(v, w): v must be callable

If the current signature were merely extended, then I believe the new 
signature would have to be (if possible)
iter(*args, *, stop_iter=<private exception>)
But having parameter args[1] (sentinel) be position-only, with no 
default, while added parameter stop_iter is keyword only, with a 
(private) default, would be a bit weird.

So instead I would suggest making the new signature be
iter(iter_or_call, sentinel=<private object>, stop_iter=<private 
exception>). If sentinel and stop_iter are both default, use current n=1 
code, else pass all 3 args to modified callable_iterator that compares 
sentinel to return values and catches stop_iter exceptions.

Either way, the user could choose to only stop on a return value, only 
stop on an exception, or stop on either with the two values not having 
to be the same. The only thing that would break is code that depends on 
a TypeError, but we allow ourselves to do that to extend functions.
'''

iter(iter_or_call, sentinel=<private object>, stop_iter=<private exception>)

is still my current proposal. Serhiy suggested 'stop_iter=StopIteration' 
and I will explain separately why I think that this would not work.

-- 
Terry Jan Reedy



More information about the Python-ideas mailing list