Using functional tools

Alex Martelli aleax at aleax.it
Sat May 4 07:58:41 EDT 2002


RPM1 wrote:
        ...
> def pick(L,I):
>     result = []
>     for i in I:
>         result.append(L[i])
>     return result
> 
> My extension is 4 times faster than the Python code.  I wonder
> if there is a pure Python functional way that is as fast as the

Not by a factor of 4, though getting about 2-times speedup is easy:

def pick1(L,I):
    result = []
    for i in I:
        result.append(L[i])
    return result

def pick2(L, I):
    return [L[i] for i in I]

def pick3(L, I):
    result = I[:]
    for i in range(len(I)):
        result[i] = L[I[i]]
    return result

import Numeric

def pick4(L, I):
    return Numeric.take(L,I)


import time, random, string
L = list(string.lowercase)
I = [random.randrange(len(L)) for i in range(100000)]

ref = None

def timer(fun):
    start = time.clock()
    result = fun(L, I)
    stend = time.clock()
    global ref
    assert ref is None or ref==result
    ref = result
    print fun.func_name,stend-start

for f in pick1, pick2, pick3, pick4:
    timer(f)

[alex at lancelot cb]$ python -O s.py
pick1 0.12
pick2 0.09
pick3 0.08
pick4 0.02
[alex at lancelot cb]$ python -O s.py
pick1 0.12
pick2 0.09
pick3 0.08
pick4 0.02

Numeric, as you see, seem even faster than your extension
(6 times, rather than 4 times, as fast as the slowest Python
code, the one you give as reference).  I hope it _is_ well
known that Numeric is often quite worthwhile even for heavy
array manipulations that have nothing particularly 'numeric'
about them:-).

Personally, unless I was already using Numeric for something
else in the program, I'd just code the list comprehension --
unless and until measurements showed that these few hundredths
of a second (for index-lists of a hundred thousand items) are
part of my program's bottlenecks, of course, in which case I'd
turn to Numeric.


Alex




More information about the Python-list mailing list