[Python-ideas] Add stop=exception option to next() (was Re: PEP 479 and take())
Terry Reedy
tjreedy at udel.edu
Sun Dec 14 01:39:25 CET 2014
On 12/13/2014 5:36 PM, Antoine Pitrou wrote:
> On Sat, 13 Dec 2014 17:31:36 -0500
> Terry Reedy <tjreedy at udel.edu> wrote:
>
>> On 12/13/2014 7:45 AM, Oscar Benjamin wrote:
>>> On 10 December 2014 at 18:35, Guido van Rossum <guido at python.org> wrote:
>>
>>> If you had both next() and take() to choose from then the only time
>>> next() would be preferable is when you want to leak StopIteration (a
>>> pattern that is now largely broken by PEP 479).
>>>
>>>> BTW did you know that next(iterator, default) returns default if the
>>>> iterator is exhausted? IOW this will never raise StopIteration. It's similar
>>>> to dict.get(key, default) or getattr(obj, attrname, default).
>>>
>>> I more often find that I want an error than a default value and of
>>
>> I once proposed, either here or on python-list, and propose again,
>> that the signature of next be expanded so that the user could specify
>> the ending exception. If possible, the stop object could either be an
>> exception class, which would be called with a generic message, or an
>> exception instance.
>>
>> Then the awkward
>>
>> try:
>> item = next(it)
>> except StopIteration:
>> raise ValueError('iterable must not be empty') from None
>
> I don't remember ever needing to write such code.
Others do, whenever the first item of an iterable needs special
treatment. And others *have* forgotten to catch StopIteration when
calling next(it).
The code for reduce *is* written with such code.
>>> from functools import reduce as r
>>> r(lambda a, b: a+b, [])
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
r(lambda a, b: a+b, [])
TypeError: reduce() of empty sequence with no initial value
But the current equivalent code in the doc is buggy because it was not.
def reduce(function, iterable, initializer=None):
it = iter(iterable)
if initializer is None:
value = next(it)
else:
value = initializer
for element in it:
value = function(value, element)
return value
>>> reduce(lambda a, b: a+b, [])
Traceback (most recent call last):
File "C:\Programs\Python34\tem.py", line 11, in <module>
reduce(lambda a, b: a+b, [])
File "C:\Programs\Python34\tem.py", line 4, in reduce
value = next(it)
StopIteration
The equivalent code now would be
try:
value = next(it)
except StopIteration:
raise TypeError("reduce() of empty sequence with no initial value")
from None
http://bugs.python.org/issue23049?
That a core developer would miss this illustrates to me why the addition
is needed. With this proposal, the correct equivalent would be
value = next(it. stop=TypeError(
"reduce() of empty sequence with no initial value"))
--
Terry Jan Reedy
More information about the Python-ideas
mailing list