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

Viewed 359

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?

1 Answers
@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)
Related