-1

I want to create a function that calculates the execution time of other functions, but when I do that, I get an error like: 'int' object is not callable. What is the problem here?

import time


def square(x):
    return x**2


def timer(func):
    t1 = time.perf_counter()
    func()
    t2 = time.perf_counter()
    print(t2-t1)

timer(square(5))

3 Answers3

2

It is also possible to modify your code to make it work, but you'll have to pass in the arguments of square() into timer() after passing in the function as the first argument:

def timer(func, *args, **kwargs):
    t1 = time.perf_counter()
    func(*args, **kwargs)
    t2 = time.perf_counter()
    print(t2-t1)

timer(square, 5)

Using *args* and **kwargs lets us deal with functions with arbitrary parameters.

A more convenient way to do this is to use a decorator. It returns a wrapper function around the original function. You don't have to change much in order to time a particular function. Here's an example:

def timer(func):
    def wrapper(*args, **kwargs):
        func_name = func.__name__
        print(f"Starting {func_name}")
        
        t1 = time.perf_counter()
        output = func(*args, **kwargs)
        t2 = time.perf_counter()
        
        print(f"Total time for {func_name}: {t2 - t1:.3f} s\n")
        return output
    
    return wrapper

To use it, simply do:

@timer
def square(x):
    return x**2

square(5)

Or:

def square(x):
    return x**2

timed_square = timer(square)
timed_square(5)
0

square(5) return 25; so you're trying to run your timer on a number ;)

Try instead:

import time

def timer(func):
    def f(args):
        t1 = time.perf_counter()
        ret = func(args)
        t2 = time.perf_counter()
        print('execution time: {}'.format(t2-t1))
        return ret
    return f
    
    
def square(x):
    return x**2
    
timedSqure = timer(square)

res = timedSqure(5)
print(res)

Further, I recommend on learning decorators in python, because with decorators you can make it even more elegant by declaring:

@timer
def square(x):
    return x**2

See repl here

And last, per @Heap Overflow's comment: it doesn't make sense to time something that runs so quickly. If you want to benchmark a function you should use timeit

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
0

Your timer expects a function to call, but you're giving it the result of already calling one (and that result isn't a function).

You can do timer(lambda: square(5)) instead. Then it's your timer function that executes the (anonymous) function and thus the expression square(5) as intended.

Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65