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