Search code examples
pythonpython-3.xpython-decorators

Why python decorating function is invoked?


practice with python 3.8

import functools


def print_name2(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        print('2: {} has been called'.format(f.__name__))
        return f(*args, **kwargs)
    return wrapper


def print_name3(f):
    print('3: {} has been called'.format(f.__name__))
    return f


@print_name3
def my_str(i):
    return str(i)


@print_name2
def my_str2(i):
    return str(i)

Once I run the code, I get

3: my_str has been called

That makes me confused because I haven't made any function call yet


Solution

  • In python, decorators are executed at the point of decoration. Your code is equivalent to this:

    import functools
    
    def print_name2(f):
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            print('2: {} has been revoked'.format(f.__name__))
            return f(*args, **kwargs)
        return wrapper
    
    
    def print_name3(f):
        print('3: {} has been revoked'.format(f.__name__))
        return f
    
    def my_str(i):
            return str(i)
    my_str = print_name3(my_str)
    
    def my_str2(i):
        return str(i)
    my_str2 = print_name2(my_str2)
    

    We essentially replace my_str and my_str2 with whatever the decorator-function returns. Now, print_name2 returns a new function that prints something, hence why nothing is printed. Meanwhile, print_name3 immediately prints something, since you did not wrap it in a new function.