Pythonデコレーターは面倒だけど面倒じゃない

Pythonデコレーターは面倒だけど面倒じゃない

Pythonのデコレーターを使いこなせない

Pythonにはデコレーターという機能があります。

でも、このデコレーター、うまく使いこなせない。私も最初に勉強したときは「何に使えるのさ?」という感じでした。

デコレーターの使い方

ともあれ、デコレーターを使ってみましょう! 出力はその下にあります。

def deco(fn):
    def inr_fn(*arg):
        print('デコレーターが始まるよ!')
        res = fn(*arg)
        print('デコレーターが終わったよ!')
        return res
    return inr_fn

@deco
def my_add(a, b):
    print('a={}, b={}, a+b={}'.format(a, b, a+b))
    return a+b

if __name__ == '__main__':
    a, b = 5, 3
    my_add(a, b)
デコレーターが始まるよ!
a=5, b=3, a+b=8
デコレーターが終わったよ!

私は最初にこれを勉強したとき、こう思いました。「うわ、何に使えるんだよ」

確かに、これじゃあ何に使えるかも理解できないし、初心者ならなおさら。

やさしいPythonにもこんな感じで確か書いてあったような気がするが(もうメルカっちゃったので確認できない)、これは良くない。

じゃあどんなものなら初心者でも「これは使えそう!」と思えるのか、ちょっと考えてみた結果、こんなコードになります。

from time import time

def time_checker(fn):
    def inr_fn(*arg):
        start = time()
        res = fn(*arg)
        print('かかった時間:', time()-start)
        return res
    return inr_fn

@time_checker
def my_add(a, b):
    print('a={}, b={}, a+b={}'.format(a, b, a+b))
    return a+b

if __name__ == '__main__':
    a, b = 5, 3
    my_add(a, b)
a=5, b=3, a+b=8
かかった時間: 5.412101745605469e-05

このプログラムを使えば、関数内でかかっている時間を確認することができます。何に使えるか、と言われたら、競技プログラミングとかで時間内で解けているかどうかとか、作成したアルゴリズムがいくつかあったときにどちらの方が早く処理できているのかを確認するときとかに使えます。

クラスで使うときはちょっと大変

クラス内で使うときはちょっと大変です。

class MyClass(object):

    def __init__(self):

        pass


    def my_deco(fn):
        def inr_fn(self):
            li_len = 15

            for i in range(li_len):
                print(fn(self, n=i))

        return inr_fn


    @my_deco
    def my_fn(self, n=0) -> str:

        return '{} ** 2 == {}'.format(n, n**2)



if __name__ == '__main__':

    mc = MyClass()
    mc.my_fn()

selfの位置は内部関数になるんだなあという感じでした。

まとめ

デコレーターは最初のうち「何に使えるか分かんない」という感じでしたが、使い慣れるとめっちゃ使うことになります。

Pythonも奥が深いんだなあ。