デコレーターがよくわからんのでワチャワチャ書く

掲題の件、そういう事です。

# -*- coding: utf-8 -*-
def show_message(f):
    def wrapper():
        print("==== function call ====")
        f()
    return wrapper

def spam1():
    return 1

@show_message
def spam2():
    return 2
    
if __name__ == "__main__":
    print(spam1())
    print("")
    print(spam2())

実行結果

1

==== function call ====
None

spam2を呼び出すとwrapper関数がさも実行されたように見える。
つまり、

  • show_message関数の引数としてspam2がfとして渡され、それを呼び出す関数としてwrapperが返却されspam2に再代入されている

というイメージか。

もうちょっと引数周りをいじってみて、確信を得る。

# -*- coding: utf-8 -*-
def show_message(f):
    def wrapper(x,y):
        print("==== function call ====")
        return f(x+y)
    return wrapper

@show_message
def spam2(x):
    return x*10
    
if __name__ == "__main__":
    print(spam2(10,5))

実行結果。

==== function call ====
150

元のspam2には引数としてxしか記述していないが、実際はwrapper関数がspam2として動作するので、2つの引数x,yが必要になるということだな。
結果も10+5という引数がf(spam2)に渡されてその値が10倍されて返ってくるので150と。
デコレーターを使わないで書くと以下と等価ということだ。下のコードだとspam2がまさにshow_messageによって”デコレート”されているのがわかる。

# -*- coding: utf-8 -*-
def show_message(f):
    def wrapper(x,y):
        print("==== function call ====")
        return f(x+y)
    return wrapper

def spam2(x):
    return x*10
    
if __name__ == "__main__":
    spam2 = show_message(spam2)    
    print(spam2(10,5))

実行結果

==== function call ====
150