[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