Python 2.0b1 List comprehensions are slow
Kevin O'Connor
koconnor at cse.buffalo.edu
Thu Sep 7 22:09:11 EDT 2000
Hello,
I've been using python and advocating it for several years now. However, I
haven't been keeping up with all the new features proposed on c.l.py. (Or
the legal battles either?) After reading about the new features in the 2.0
beta, I knew I had to download a copy and take a look.
First of all, the list comprehension feature has to be one of the NICEST
features to be added to the language. After reading about it, and writing
some test programs I was one step short of killing off all those ugly map
and operator calls in all my old programs. The comprehensions are much
easier to read than a mangled map setup, and they have the potential to be
just as fast and significantly more flexible.
Unfortunately, I'm a little concerned about the speed of the new list
feature. According to the web site, "[a comprehension] is more efficient
than map() with a lambda." However, this is not true in my test programs -
they show comprehensions to be 50% slower than map with a lambda.
I hope this can be resolved before 2.0 is released. :-)
-Kevin
Sample output from my program (on a dual Celeron 366, linux 2.4.0-test7) :
Many repeated calls on small lists:
map + operator: 12.11 cpu seconds
map + lambda: 12.82 cpu seconds
comprehensions: 18.59 cpu seconds
One call on a large list:
map + operator: 6.87 cpu seconds
map + lambda: 7.04 cpu seconds
comprehensions: 11.84 cpu seconds
Test program:
#!/usr/bin/env python
import operator
import time
vals = [1, 8, 12, 89, 325, 213, 23, 434, 435, 2435, 5, 45, 423, 435, 324, 5234]
print "Accuracy test:"
print "foo1: %s" % map(operator.add, (12,)*len(vals), vals)
print "foo2: %s" % map(lambda x: x+12, vals)
print "foo3: %s" % [ x+12 for x in vals]
print
def timeit(func):
st = time.clock()
func(vals)
en = time.clock()
return en - st
counter = range(200000)
def foo1(arry):
dummyarry = (12,) * len(arry)
operator__add = operator.add
__map = map
for i in counter:
__map(operator__add, dummyarry, arry)
def foo2(arry):
__map = map
func = (lambda x: x+12)
for i in counter:
__map(func, arry)
def foo3(arry):
for i in counter:
[ x+12 for x in arry]
print "Many repeated calls on small lists:"
print "map + operator: %s cpu seconds" % timeit(foo1)
print "map + lambda: %s cpu seconds" % timeit(foo2)
print "comprehensions: %s cpu seconds" % timeit(foo3)
print
def bar1(arry):
return map(operator.add, (12,)*len(arry), arry)
def bar2(arry):
return map(lambda x: x+12, arry)
def bar3(arry):
return [ x+12 for x in arry]
vals = range(2000000)
print "One call on a large list:"
print "map + operator: %s cpu seconds" % timeit(bar1)
print "map + lambda: %s cpu seconds" % timeit(bar2)
print "comprehensions: %s cpu seconds" % timeit(bar3)
print
--
------------------------------------------------------------------------
| Kevin O'Connor "BTW, IMHO we need a FAQ for |
| koconnor at cse.buffalo.edu 'IMHO', 'FAQ', 'BTW', etc. !" |
------------------------------------------------------------------------
More information about the Python-list
mailing list