Search code examples
pythonpython-3.xpython-decorators

Python decorator prints "none"


import random
import time

def timeit(func):

    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        print ("{} took {} secs \n".format(func.__name__, time.time() - start))
    return wrapper


@timeit
def insort(l):
    """ Uses insetion sort for sorting list """

    for i in range(1, len(l)): 
        temp = l[i]
        j = i
        while j > 0 and l[j - 1] > temp:
            l[j] = l[j - 1]
            j -= 1
            l[j] = temp
    return l


@timeit
def bublesort(l):
    """ Uses insetion sort for sorting list """

    for i in range(len(l)-1, 0, -1):
        for j in range(i):
            if l[j] > l[j+1]:
                l[j], l[j+1] = l[j+1], l[j]
    return l


x =random.sample(range(2000), 1000) 
print (insort(x[:]))
print (bublesort(x[:]))

Above code outputs:

insort took 0.0629999637604 secs 

None
bublesort took 0.104000091553 secs 

None

Why it is printing none after every result and how can I prevent it? Also I am new to decorators so I would like to know if there is any better way for timing my code.


Solution

  • Your wrapper, which replaces the original function, ignores the return value and returns None.

    Make the following change:

    def timeit(func):
    
        def wrapper(*args, **kwargs):
            start = time.time()
            ret = func(*args, **kwargs)
            print ("{} took {} secs \n".format(func.__name__, time.time() - start))
            return ret
        return wrapper
    

    This will make your decorator work properly. If you want to avoid printing the return values, change

    print (insort(x[:]))
    print (bublesort(x[:]))
    

    to just

    insort(x[:])
    bublesort(x[:])
    

    In general, if you don't want to print something, don't pass it to print.