Brilliant or insane code?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Mar 17 22:25:45 EDT 2015


On Wednesday 18 March 2015 12:14, Dan Sommers wrote:

> On Wed, 18 Mar 2015 00:35:42 +0000, Mark Lawrence wrote:
> 
>> I've just come across this
>> http://www.stavros.io/posts/brilliant-or-insane-code/ as a result of
>> this http://bugs.python.org/issue23695
>> 
>> Any and all opinions welcomed, I'm chickening out and sitting firmly
>> on the fence.
> 
> According to the article itself, "it relies in an implementation detail
> (the order the zip function iterates over the arrays) to work."  Then
> again, the article also points to the official docs that says that this
> implementation detail is guaranteed.

That means it isn't an implementation detail, it's interface. Consider:

"This relies on an implementation detail that len() of a list returns the 
number of items of the list. P.S. the documentation guarantees that len() of 
a list will return the number of items of the list."


The technique being used neither brilliant nor insane. At most, it is a 
moderately clever way of grouping values. It's a Neat Trick that every 
Python programmer should learn.

py> data = list("abcdefghijklmno")
py> zip(*[iter(data)]*3)
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('j', 'k', 'l'), ('m', 
'n', 'o')]


How it works is simple. Create an iterator from your data sequence, then 
call zip with 3 arguments of *the same* iterator (not 3 separate iterators). 
Since zip() is guaranteed to call next(iterator) in left-to-right order, 
this is more or less the same as:

def group(data):
    it = iter(data)
    while True:
        accum = []
        for i in range(3):
            accum(next(it))
        yield tuple(accum)


modulo error handling. The syntax is a bit Perlish, but every part of the 
code is absolutely straight-forward and standard Python semantics:

zip(*[iter(data)]*3):


    iter(data)  # trivial, make an iterator from an iterable

    [iter(data)]  # put it in a list

    [iter(data)]*3  # list replication -- 3 references to the same iterator

    *[iter(data)]*3  # expand to three arguments

    zip(...)  # and zip 'em up from left to right




-- 
Steve




More information about the Python-list mailing list