Pythonデコレータについて

はじめに

Pythonのデコレータについて理解したので書いていきます。

デコレータとはなにか?

関数に機能を付け足す事を簡単にする機能のこと。

デコレータを理解しよう

デコレータを理解するためには4つのステップがあると思っています。

(1) 関数の引数に関数を入れられる。

def function1():
    print("HelloWorld")

def function2():
    print("NewWorld")

def function3(f):
    print("A")
    f()
    print("B")

function3(function1)//function1にはカッコを付けない

//出力
//A
//HelloWorld
//B

function3(function2)//function2にはカッコを付けない

//出力
//A
//NewWorld
//B

(2) 関数をreturnできる

def function1():
    def function2():
        print("Hello")
    return function2//カッコつけない

x=function1()
//xにはfunction2が入っている

x()
//出力
//Hello

function1()()
//これは上のx()と同じ
//出力
//Hello

(3) 1と2を使い関数を装飾する

def function1(f):
    def function2():
        //if文などを書いてもヨシ
        print("++++++++++")//装飾
        f()
        print("++++++++++")//装飾
    return function2

def function3():
    print("World")

x=function1(function3)
//xは関数

x()
//出力
//++++++++++
//World
//++++++++++

function1(function3)()
//上のx()と同じ
//出力
//++++++++++
//World
//++++++++++

(4)デコレータ


def function1(f):
    def function2():
        //if文などを書いてもヨシ
        print("++++++++++")//装飾
        f()
        print("++++++++++")//装飾
    return function2

@function1
def function3():
    print("World")

function3()
//出力
++++++++++
World
++++++++++

(3)と(4)でのfunction1とfunction2は全く同じ。

デコレータを使うメリット


@をつけるだけで普通のコードをそのまま使っているように感じることができる。
装飾されているのがわかりやすい

デメリット


なにが装飾されているかわかりにくい(function1とfunction2は普通隠されているため)

補足
(1)function1で関数を返す必要がなさそう?

def function1(f):
    print("++++++++++")
    f()
    print("++++++++++")

def function2():
    print("HelloWorld")

function1(function2)

//出力
++++++++++
HelloWorld
++++++++++

この場合だと出力が同じで関係なさそうですが、よく考えてみると引数に問題が生じてしまいます。

def function1(f):
    print("++++++++++")
    //Sはどこ?
    f(S)
    print("++++++++++")

def function3(S:str)->str:
    print(S)
    return S+"World"

S="Hello"
function1(function3)

この状態だとf(S)に値を入れられません。
しかし関数で返すと


def function1(f):
    def function2(S:str)->str:
        print("++++++++++")
        x=f(S)
        print("++++++++++")
        return x
    return function2

def function3(S:str)->str:
    print(S)
    return S+"World"

S="Hello"
x=function1(function3)(Hello)

//出力
++++++++++
Hello
++++++++++

print(x)
//出力
HelloWorld

となります。

可変長引数

def function1(f):
    def function2(*args,**kwargs)->str:
        print("++++++++++")
        x=f(args)
        print("++++++++++")
        return x
    return function2

def function3(S:str)->str:
    print(S)
    return S+"World"

S="Hello"
x=function1(function3)(Hello)

function2の引数を(*args,**kwargs)とどんな関数でも受け取れます。

終わりに

デコレータを使うと関数に機能を追加するのが楽!

間違ってたりしたら教えてください
pythonのコメントは#でした。
(直さないのは直すのが面倒だけ)

いいなと思ったら応援しよう!