dot operations

Steven D'Aprano steve at REMOVE.THIS.cybersource.com.au
Thu Jan 11 15:10:02 EST 2007


On Thu, 11 Jan 2007 06:06:39 -0800, jm.suresh at no.spam.gmail.com wrote:

>> jm.suresh at no.spam.gmail.com wrote:
>> > Hi,
>> >  Frequently I get to do like this:
>> > a = (1, 2, 3, 4) # some dummy values
>> > b = (4, 3, 2, 1)
>> > import operator
>> > c = map(operator.add, a, b)
>> >
>> > I am finding the last line not very readable especially when I combine
>> > couple of such operations into one line. Is it possible to overload
>> > operators, so that, I can use .+ for element wise addition, as,
>> > c = a .+ b
>> > which is much more readable.

[snip]

> I just found this from :
> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/384122
> 
> class Infix(object):

[snip code]

> c = a |dotplus| b


Personally, I find that to be the least readable of all the alternatives.
It is also slow, so slow that using it is (in my opinion) a pessimation
rather than an optimization.

Let me make the usual warnings about premature optimization being
the root of all evil, blah blah blah. Readability counts, and nobody cares
if you shave one hundredth of a millisecond off some code that your
program runs once. But, having said that, map is *fast*, especially with
the functions from operator.

>>> import timeit
>>> timeit.Timer("map(operator.add, a, b)", 
... "import operator; a = (1, 2, 3, 4); b = (4, 3, 2, 1)").timeit()
4.0072550773620605

It is even faster if you get rid of the dot lookup:

>>> timeit.Timer("map(add, a, b)", "from operator import add; "
... "a = (1, 2, 3, 4); b = (4, 3, 2, 1)").timeit()
3.6557090282440186

Using lambda can be much slower:

>>> timeit.Timer("map(lambda x,y: x+y, a, b)", 
... "a = (1, 2, 3, 4); b = (4, 3, 2, 1)").timeit()
6.1221940517425537

A list comprehension is in the middle, speed-wise:

>>> timeit.Timer("[x+y for x,y in zip(a,b)]", 
... "a = (1, 2, 3, 4); b = (4, 3, 2, 1)").timeit()
5.0318419933319092

But the Infix recipe is slower than a wet week:

>>> timeit.Timer("a|dotplus|b", 
... "a = (1, 2, 3, 4); b = (4, 3, 2, 1); " 
... "from __main__ import dotplus").timeit()
15.195909976959229


Speaking for myself, I find list comprehensions to be the most readable of
the alternatives and the most Pythonic. 



-- 
Steven.




More information about the Python-list mailing list