デコレータの基本について理解したのでまとめる
Pythonのデコレータに関して、理解していることをまとめてみる。
@
を使ったデコレータの書き方はただのシンタックスシュガー
(読み書きのしやすさのために導入される構文)。
それでは、何に対するシンタックスシュガーなのか。
まず、以下のようなプログラムがあるとする。
def egg(): return "egg" if __name__ == '__main__': print(egg()) # egg
実行すると、当たり前だが以下の様な結果になる。
egg
次に、先ほどのファイルにscramble
というメソッドを追加する。
def scramble(egg): def _scramble(): return "scramble " + egg() + "!" return _scramble def egg(): return "egg" if __name__ == '__main__': scramble_egg = scramble(egg) print(scramble_egg()) # scramble egg!
scramble
メソッドは、オブジェクトを1つ受け取り、内部に定義されている_scramble
メソッドを返している。
つまり、scramble
メソッド自体は引数に対して何かを行うことはなく、
ただ内部のメソッドを返しているだけの機能しか持っていない。
返される内部メソッドの_scramble
は、scramble
メソッドが受け取ったの返り値に、
"scramble "と"!"という文字列を装飾(デコレート)して返している。
if __name__ == '__main__'
では、scramble
メソッドにegg
メソッド渡し、
返り値をscramble_egg
という変数に格納している。
scramble
メソッドの返り値は_scramble
のため、scramble_egg
変数は
_scramble
メソッドの内容と同じ挙動をする。
そのため、ファイルを実行すると以下の様な実行結果になる。
scramble egg!
さて、if __name__ == '__main__'
の中ではscramble
メソッドの返り値はscramble_egg
という変数に格納していた。
ここで、すでに定義されているegg
メソッドにscramble
の返り値を格納してみる。
Pythonはメソッドも変数も全てがオブジェクトのため、こういうことができる。
def scramble(egg): def _scramble(): return "scramble " + egg() + "!" return _scramble def egg(): return "egg" if __name__ == '__main__': egg = scramble(egg) # この部分と print(egg()) # この部分
実行結果は上記と同じscramble egg!
。
egg
に対してscramble
メソッドの返り値を格納しているため、egg
メソッドは
元の「"egg"という文字列を返す」という機能が上書きされている。
しかし、ただ上書きされたわけではなく、scramble
メソッドに元の機能を引数として渡しているため、
「"egg"という文字列を返す」機能は、_scramble
内で使われることになる。
この状態におけるscramble
メソッドがデコレータとなる。
文字通り別のメソッドを装飾することができる。
これまでの手順を@
を使って書き換えると、以下のようなコードになる。
def scramble(egg): def _scramble(): return "scramble " + egg() + "!" return _scramble @scramble def egg(): return "egg" if __name__ == '__main__': print(egg()) # scramble egg!