pythondecoratorpython-decorators

How a decorator can register a function without a formal call?


I am looking at one of the examples from here, in particular at the following one:

import random
PLUGINS = dict()

def register(func):
    """Register a function as a plug-in"""
    PLUGINS[func.__name__] = func
    return func

@register
def say_hello(name):
    return f"Hello {name}"

@register
def be_awesome(name):
    return f"Yo {name}, together we are the awesomest!"

def randomly_greet(name):
    greeter, greeter_func = random.choice(list(PLUGINS.items()))
    print(f"Using {greeter!r}")
    return greeter_func(name)

What stucks me is that neither say_hello() nor be_awesome() functions are called until the very last line, but PLUGINS already contains both of them. I am used to think that decorators are applied while the functions are explicitly called, but this example tells me that I was wrong. Does this happen because register function does not call func? But what if it does call? Is this a special case to remember or is there some system behind it?


Solution

  • @register
    def say_hello(name):
        return f"Hello {name}"
    

    is equivalent to:

    def say_hello(name):
        return f"Hello {name}"
    
    say_hello = register(say_hello)