PythonのDecorator(概要編)

はじめに

Pythonでは関数にDecoratorを簡単に適用できる構文が標準で組み込まれています。
今回はこの構文をみていきます。

PythonのDecoratorとは

Python用語集の定義によると

A function returning another function, usually applied as a function transformation using the @wrapper syntax.

PythonのDecoratorは、関数を変換する関数で、@…と言った感じの構文使う。とのことです。

この構文はPython2.4で導入されていますが、PEP318みてみると

The current method for transforming functions …can lead to code that is difficult to understand. Ideally, these transformations should be made at the same point in the code where the declaration itself is made.

とあるので、関数を変換する関数の可読性向上がこの構文の目的のようです。

では、さっそくサンプルを書いていきます。

Decorator構文を使ったサンプル

Decoratorが動作する仕組みについても触れたいところですが、長くなりそうなので、この記事ではサンプルを載せるのみに一旦留め、別記事でDecoratorの動作する仕組みを書こうと思います。

ここでは、以下仕様のサンプルを載せます。

動作仕様

  • Decoratorを関数に適用すると、その関数の実行時間がプリントされる
  • Decoratorが適用される側の関数は、ランダムな数値1000個の和を計算するだけの関数

ソースコード

関数の実行時間をプリントするDecorator

from functools import wraps
def deco_func(func):
    @wraps(func)
    def measure_time(*args, **kwargs):
        t1 = time.time()
        result = func(*args, **kwargs)
        t2 = time.time()
        print(func.__name__ + " took " + format(t2 - t1, ".3f") + " seconds.")
        return result
    return measure_time

ランダムな数値100個の和を計算するだけの関数(上記Decoratorを適用)

import random
@deco_func
def random_add():
    x = 0
    for i in range(1000):
        x += random.randint(0, 100)
    print("Calculation finish.")
    return x

関数を実行するmain

if __name__ == '__main__':
    random_add()

実行結果

Calculation finish.
random_add took 0.003 seconds.

こんな感じでrandom_add関数にDecorator(deco_func)を適用することで、実行時間が出力できるようになりました。

このサンプルのポイント

  • Decorator関数を適用する関数は、 @デコレータ関数名(この例ではdeco_func)をつける
  • Decorator関数は、変換対象の関数を引数(この例ではfunc)にとり
  • 変換後の関数を戻り値にする(この例ではmeasure_time)
  • 変換後の関数は、引数から受け取った関数(この例ではfunc)の実行の前に開始時間、後に終了時間を取得し、その差分をプリントしている

まとめ

こんな感じでPythonでは、Decorator構文を使うことで、関数の元の機能を壊さず、新たな機能を付加することが簡単にできます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA