Decorator execution order Decorator execution order python python

Decorator execution order


Decorators wrap the function they are decorating. So make_bold decorated the result of the make_italic decorator, which decorated the hello function.

The @decorator syntax is really just syntactic sugar; the following:

@decoratordef decorated_function():    # ...

is really executed as:

def decorated_function():    # ...decorated_function = decorator(decorated_function)

replacing the original decorated_function object with whatever decorator() returned.

Stacking decorators repeats that process outward.

So your sample:

@make_bold@make_italicdef hello():  return "hello world"

can be expanded to:

def hello():  return "hello world"hello = make_bold(make_italic(hello))

When you call hello() now, you are calling the object returned by make_bold(), really. make_bold() returned a lambda that calls the function make_bold wrapped, which is the return value of make_italic(), which is also a lambda that calls the original hello(). Expanding all these calls you get:

hello() = lambda : "<b>" + fn() + "</b>" #  where fn() ->    lambda : "<i>" + fn() + "</i>" # where fn() ->         return "hello world"

so the output becomes:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"