[Python-ideas] Rewriting the "roundrobin" recipe in the itertools documentation
mertz at gnosis.cx
Thu Nov 16 10:08:56 EST 2017
I agree this is a much better recipe presented.
Have you benchmarked the two on more realistically long iterators. E.g. a
hundred iterators of millions of items where many terminate much earlier
than others. I doubt the repeated 'is not' comparison makes much
difference, but it would be good to see.
On Nov 16, 2017 5:57 AM, "bunslow" <bunslow at gmail.com> wrote:
> For taking values alternately from a series of iterables, there's two
> primary functions:
> zip of course stops when the shortest iterable ends. zip_longest is
> generally a useful substitute for when you don't want the zip behavior, but
> it fills extra values in the blanks rather than just ignoring a finished
> iterator and moving on with the rest.
> This latter most use case is at least somewhat common, according to
> this StackOverflow question (and other duplicates), in addition to the
> existence of the `roundrobin` recipe in the itertools docs. The recipe
> satisfies this use case, and its code is repeated in the StackOverflow
> However, it is remarkably unpythonic, in my opinion, which is one thing
> when such is necessary to achieve a goal, but for this functionality, such
> is most definitely *not* necessary. I'll paste the code here for quick
> def roundrobin(*iterables):
> "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
> pending = len(iterables)
> nexts = cycle(iter(it).__next__ for it in iterables)
> while pending:
> for next in nexts:
> yield next()
> except StopIteration:
> pending -= 1
> nexts = cycle(islice(nexts, pending))
> Things that strike me as unpythonic: 1) requiring the total number of
> input iterables 2) making gratuitous use of `next`, 3) using a while loop
> in code dealing with iterables, 4) combining loops, exceptions, and
> composed itertools functions in non-obvious ways that make control flow
> difficult to determine
> Now, I get it, looking at the "roughly equivalent to" code for zip_longest
> in the docs, there doesn't seem to be much way around it for generally
> similar goals, and as I said above, unpythonic is fine when necessary
> (practicality beats purity), but in this case, for being a "recipe" in the
> itertools docs, it should *make use* of the zip_longest which already does
> all the unpythonic stuff for you (though honestly I'm not convinced either
> that the zip_longest code in the docs is the most possible pythonic-ness).
> Instead, the following recipe (which I also submitted to the StackOverflow
> question, and which is generally similar to several other later answers,
> all remarking that they believe it's more pythonic) is much cleaner and
> more suited to demonstrating the power of itertools to new developers than
> the mess of a "recipe" pasted above.
> def roundrobin(*iters):
> "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
> # Perhaps "flat_zip_nofill" is a better name, or something similar
> sentinel = object()
> for tup in it.zip_longest(*iters, fillvalue=sentinel):
> yield from (x for x in tup if x is not sentinel)
> In particular, this is just an extremely thin wrapper around zip_longest,
> whose primary purpose is to eliminate the otherwise-mandatory "fillvalues"
> that zip_longest requires to produce uniform-length tuples. It's also an
> excellent example of how to make best pythonic use of iterables in general,
> and itertools in particular, and as such a much better implementation to be
> demonstrated in documentation.
> I would thus advocate that the former recipe is replaced with the latter
> recipe, being much more pythonic, understandable, and useful for helping
> new developers acquire the style of python. (Using the common linguistics
> analogy: a dictionary and grammar for a spoken language may be enough to
> communicate, but we rely on a large body of literature -- fiction,
> research, poetry, etc -- as children to get that special flavor and most
> expressive taste to the language. The stdlib is no Shakespeare, but it and
> its docs still form an important part of the formative literature of the
> Python language.)
> I realize at the end of the day this is a pretty trivial and ultimately
> meaningless nit to pick, but I've never contributed before and have a
> variety of similar minor pain points in the docs/stdlib, and I'm trying to
> gauge 1) how well this sort of minor QoL improvement is wanted, and 2) even
> if it is wanted, am I going about it the right way. If the answers to both
> of these questions are positive regarding this particular case, then I'll
> look into making a BPO issue and pull request on GitHub, which IIUC is the
> standard path for contributions.
> Thank you for your consideration.
> : https://stackoverflow.com/questions/3678869/pythonic-
> : https://docs.python.org/3/library/itertools.html#itertools-recipes
> Python-ideas mailing list
> Python-ideas at python.org
> Code of Conduct: http://python.org/psf/codeofconduct/
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-ideas