[Tutor] map() and lambda to change class instance attribute (fwd)

Kent Johnson kent37 at tds.net
Mon May 16 12:09:31 CEST 2005


Bernard Lebel wrote:
> Hi Kent,
> 
> So if I undestand you right, mapping a function with map() when it is
> a built-in function will/may be faster than a for loop, but if it's a
> custom function (ie. a def one), it will most likely be slower?

I guess I didn't proofread that last mail...what I meant is

- Write the code for clarity first
- If you find a performance bottleneck then test different solutions to see which is fastest for 
your actual data and usage.
- Mapping a builtin function over a list is relatively fast in Python and it is worth trying if it 
meets your needs.
- Calling a function is relatively expensive in Python so if using map() requires you to define a 
helper that may wipe out its advantage.
- Testing is crucial! Guessing is only good for helping to come up with ideas to test.

Here is a program that tests six ways to apply a function to elements of a list. The functions don't 
create new lists except as side effects since that was the original problem. They use map(), list 
comprehension and an explicit for loop to apply str() or a Python function returning str() to the 
elements of a list. (The list already contains strings so the actual function call should be fast.)

####

import timeit

data = [str(n) for n in range(100)]

def strByMap():
     map(str, data)

def strByListComp():
     [str(n) for n in data]

def strByLoop():
     for n in data:
         str(n)


def func(x):
     return str(x)


def funcByMap():
     map(func, data)

def funcByListComp():
     [func(n) for n in data]

def funcByLoop():
     for n in data:
         func(n)


def timeOne(fn):
     setup = "from __main__ import " + fn.__name__
     stmt = '%s()' % (fn.__name__)

     t = timeit.Timer(stmt, setup)
     secs = min(t.repeat(number=1000))
     print '%15s %s' % (fn.__name__, secs)

for fn in [ strByMap, strByListComp, strByLoop, funcByMap, funcByListComp, funcByLoop ]:
     timeOne(fn)

###

Here are the results on my computer:

        strByMap 0.0359623918682
   strByListComp 0.0581065470611
       strByLoop 0.0481150537289
       funcByMap 0.0810943849009
  funcByListComp 0.0891375859222
      funcByLoop 0.0806144356336

So for this test, map is fastest when calling a builtin and explicit looping is fastest when calling 
a function. With the explicit loop you might be able to inline the function, in which case it would 
be much faster than either map or list comp.

Modifying the program slightly so that each function actually creates a list changes the results 
dramatically:
        strByMap 0.0365733633744
   strByListComp 0.0579948010152
       strByLoop 0.0764722890758
       funcByMap 0.0811885309446
  funcByListComp 0.0883995032888
      funcByLoop 0.10586876265

Now map() is fastest in both cases, though a for loop with inlined code beats map() with an external 
function.

Kent
> 
> 
> Thanks
> Bernard
> 
> 
> On 5/13/05, Kent Johnson <kent37 at tds.net> wrote:
> 
>>Bernard Lebel wrote:
>>
>>>The authors even go as far as saysing, on page 228 (first paragraph)
>>>that map() used that way has a performance benefit and is faster than
>>>a for loop.
>>
>>That may well be correct, at least in the case where the function passed to map is a builtin.
>>Mapping a builtin to over a list is extremely fast. So write the code with a for loop so it is
>>clear. When you identify a performance bottleneck you can try rewriting your loop using map or list
>>comprehension, which is also fast. Until then it is premature optimization. For typical loops over a
>>small number of items I can't imagine you would notice the difference.
>>
>>Kent
>>
>>_______________________________________________
>>Tutor maillist  -  Tutor at python.org
>>http://mail.python.org/mailman/listinfo/tutor
>>
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 



More information about the Tutor mailing list