# [Tutor] Calling a function

Joal Heagney jhe13586 at bigpond.net.au
Thu Jun 9 10:50:53 CEST 2005

```Kevin Reeder said:

>def do_timing(num_times, *funcs):

Took me a while to work out what went wrong, but the first part occurs here. The *funcs bit means that any extra arguments passed to do_timing will be put into a tuple called funcs.

So do_timing(100, dosomething, dosomethingelse)
will pass the following arguments to the body of the function:

num_times = 100
funcs = (dosomething, dosomethingelse)

>    totals = {}
>    for func in funcs: totals[func] = 0.0

You may want to recode this bit as well. I'll cover that in the PS.

>	for x in range(num_times):
>	for func in funcs:
>	    starttime = time.time()
>	    apply(func)
>	    stoptime = time.time()
>	    elapsed = stoptime-starttime
>	    totals[func] = totals[func] + elapsed
>	 for func in funcs:
>	     print "Running %s %d times took %.3f seconds" %
>(func.__name__, num_times, totals[func])
>
>do_timing(100, (makezeros.lots_of_appends, makezeros.one_multiply))

And here's the next part of the problem. Instead of letting do_timing wrap the extra arguments up into a tuple for you:

do_timing(100, makezeros.lots_of_appends, makezeros.one_multiply)

You are wrapping your two functions up as a tuple. So the do_timing function recieves the following when it starts:

num_times = 100
funcs = ((makezeros.lots_of_appends, makezeros.one_multiply),)
I.e. one entry which is a tuple.

>Here's the outcome I get:
>
>\$ python ./Python/timings.py
>Traceback (most recent call last):
>  File "./Python/timings.py", line 17, in ?
>    do_timing(100, (lots_of_appends, one_multiply))
>  File "./Python/timings.py", line 10, in do_timing
>    apply(func)
>TypeError: 'tuple' object is not callable

And that is why you get this TypeError. When you pass the first component of funcs to the apply(funcs) bit, you're asking python to do the following:

apply((makezeros.lots_of_appends, makezeros.one_multiply))

Which python can't/won't do. *grins*

P.S.
You ask the code to set all total[funcs] = 0.0
Then you ask the code to calculate the timings of each function.
Then you ask the code to print the timings for eac function.

You're looping through the same data set three times. Even if you want the timings to print last, you can optimize you're code a little bit by doing the following:

def do_timing(num_times, *funcs):
totals = {}
for func in funcs:
totals[func] = 0.0
for x in range(num_times):
starttime = time.time()
apply(func)
stoptime = time.time()
elapsed = stoptime-starttime
totals[func] = totals[func] + elapsed
for func in funcs:
print "Running %s %d times took %.3f seconds" % (func.__name__, num_times, totals[func])

Have fun!

```