[Python-ideas] PEP 479 and take()

Oscar Benjamin oscar.j.benjamin at gmail.com
Sat Dec 13 13:45:36 CET 2014


On 10 December 2014 at 18:35, Guido van Rossum <guido at python.org> wrote:
> Hm... The type of take() seems schizophrenic: take() with one argument
> returns a single item, while take() with a count returns a tuple of that
> many items. It would be better if these were two separate functions.

Fair enough. It seemed like a natural extension to me but since it can
easily be done with a list comprehension it's not really necessary.

> Other
> than that, it's a simple function that people can easily code up themselves
> (or perhaps there's already a variant in itertools :-).

It's not hard to write your own take(). It's also not hard to call
next() properly and catch the StopIteration provided you're aware of
the danger that a loose StopIteration poses (and never make any
mistakes!).

I've made the mistake before in real code and I've seen plenty of
experienced pythoneers making it when posting snippets on this list.
I've tried to point it out where possible e.g.:
https://mail.python.org/pipermail/python-ideas/2013-February/019627.html
I guess it's just easy to reach into builtins looking for take() and
then pull out next() because take() isn't there.

The point is that while next() makes perfect sense as the canonical
way to call __next__() it is often inappropriate as an end user
function where the user simply wants to get items from an iterator.
i.e. when you're just using iterators and not consciously implementing
them next() does the wrong thing.

Consider the different uses of next():
1) You want to leak StopIteration.
2) You want to catch StopIteration.
3) You know that StopIteration will never be raised.
4) You haven't considered the StopIteration.

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
course being able to detect the default requires knowing that it
cannot be returned by the iterator. You can't always use next() this
way but when you do of course there is no problem. I don't really need
the dict.get method if I want an error since I can simply write
dict[key]. The point of PEP 479 is about silently masking an error
where loudly reporting it is considered preferable: in this case the
error is easy to avoid for someone who understands everything
perfectly and is explicitly thinking about it.


Oscar


More information about the Python-ideas mailing list