デコレータの実行順序 質問する

デコレータの実行順序 質問する
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()

出力:"<b><i>hello world</i></b>"

私はデコレータについて、またほとんどの例でデコレータがどのように機能するかについて大まかに理解しています。

この例では、 が 2 つあります。出力から、@make_italic最初に が実行され、次に が実行されているようです@make_bold

これは、装飾された関数の場合、最初に関数を実行し、次に他のデコレータの先頭に向かって移動することを意味しますか?逆ではなく、@make_italicfirst then のように。@make_bold

つまり、これはほとんどのプログラミング言語におけるトップダウンアプローチの標準とは異なるということですか? これはデコレータの場合だけですか? それとも私が間違っていますか?

ベストアンサー1

デコレーター包むデコレートする関数。つまり、関数をデコレートしたデコレータmake_boldの結果をデコレートするのです。make_italichello

構文@decoratorは実際には単なる構文糖であり、次のようになります。

@decorator
def decorated_function():
    # ...

実際には次のように実行されます:

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

元のオブジェクトを返されたdecorated_functionオブジェクトに置き換えますdecorator()

デコレータを積み重ねると、そのプロセスが繰り返されます外向き

それであなたのサンプルは次のようになります:

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

次のように拡張できます。

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

ここでを呼び出すと、実際にはhello()によって返されたオブジェクトを呼び出しています。は、ラップされた関数を呼び出すを返しました。これは の戻り値であり、これも元の を呼び出すラムダです。これらすべての呼び出しを展開すると、次のようになります。make_bold()make_bold()lambdamake_boldmake_italic()hello()

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

出力は次のようになります。

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

おすすめ記事