Zlecenie wykonania dekoratora

def make_bold(fn):
    return lambda : "<b>" + fn() + "</b>"

def make_italic(fn):
    return lambda : "<i>" + fn() + "</i>"

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

helloHTML = hello()

Wyjście: "<b><i>hello world</i></b>"

Z grubsza Rozumiem o dekoratorach i jak to działa z jednym z nich w większości przykładów.

W tym przykładzie jest ich 2. Z wyjścia wynika, że @make_italic uruchamia się najpierw, a następnie @make_bold.

Czy to oznacza, że dla dekorowanych funkcji, najpierw uruchomi funkcję, a następnie przesunie się do góry dla innych dekoratorów? Jak @make_italic Najpierw @make_bold, a nie odwrotnie.

Więc oznacza to, że jest różni się od normy podejścia odgórnego w większości języków programowania? Tylko dla tego dekoratora? A może się mylę?

Author: Martijn Pieters, 2014-12-07

1 answers

Dekoratorzy owijają funkcję, którą dekorują. Więc make_bold dekoruje wynik make_italic dekoratora, który dekoruje hello funkcję.

Składnia @decorator jest tak naprawdę tylko cukrem składniowym; następujące:

@decorator
def decorated_function():
    # ...

Jest tak naprawdę wykonywany jako:

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

Zastąpienie oryginalnego obiektu decorated_function zwracanym obiektem decorator().

Układanie dekoratorów powtarza ten proces Na Zewnątrz .

Więc twoja próbka:

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

Może być rozszerzono do:

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

Kiedy wywołujesz hello() teraz, wywołujesz obiekt zwrócony przez make_bold(), naprawdę. make_bold() zwrócił lambda, który wywołuje funkcję make_bold owiniętą, która jest wartością zwracaną make_italic(), która jest również lambda, która wywołuje Oryginalny hello(). Rozszerzenie wszystkich tych połączeń, które otrzymujesz:

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

Więc wyjście staje się:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"
 138
Author: Martijn Pieters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-07 11:45:42