python:decorator

文書の過去の版を表示しています。


Python デコレータ

 Python のデコレータは、関数やメソッドの機能を拡張することができる。

 デコレータは関数やメソッドをラップすることにより、ラップした処理の実行の有無やタイミングを制御することができる。そして、ラップした処理に対する引数や戻り値を取得して、処理の前後に独自の追加機能を実行することが可能となる。

 以下に add 関数を @func_info デコレータでラップする例を示す。

# -*- coding: utf-8 -*-
 
# 関数情報を表示するデコレータ
def func_info(func):
    # 引数 func をラップする関数を定義
    def _func_wrapper(*args, **kwargs):
        print '--- func_info ---'
        print 'func:', func
        print 'args:', args, 'kwargs:', kwargs
        # 引数 func を実行
        result = func(*args, **kwargs)
        print 'result:', result
        print '-----------------'
        # 引数 func の実行結果を返却
        return result
    # 引数 func をラップした関数を返却
    return _func_wrapper
 
# デコレートされた関数を定義
@func_info
def add(param1, param2):
    return param1 + param2
 
# デコレートされた関数を実行
print '関数実行->: add(1, 2)'
print add(1, 2)


実行結果:

関数実行->: add(1, 2)
--- func_info ---
func: <function add at 0x1644230>
args: (1, 2) kwargs: {}
result: 3
-----------------
3

 デコレータとは関数ラッパーを生成する関数であるということが言える。これらはクロージャと呼ばれる仕組みにより実現される。
 ※クロージャとは定義された環境への参照を持った関数のこと。

# 関数情報を表示するデコレータ
def func_info(func):
    # 引数 func をラップする関数を定義
    def _func_wrapper(*args, **kwargs):
        print '--- func_info ---'
        print 'func:', func
        print 'args:', args, 'kwargs:', kwargs
        # 引数 func を実行
        result = func(*args, **kwargs)
        print 'result:', result
        print '-----------------'
        # 引数 func の実行結果を返却
        return result
    # 引数 func をラップした関数を返却
    return _func_wrapper

 上記のデコレータでは、引数の func 関数をラップした _func_wrapper 関数を返却している。

 デコレータ式で add 関数をデコレートすると、add 関数は @func_info デコレータの _func_wrapper 関数ラッパーを返すようになる。

@func_info
def add(param1, param2):
    return param1 + param2
 
# add はデコレータの関数ラッパーを返すようになる
print add


実行結果:

<function _func_wrapper at 0x22f02a8>


 デコレータ式は、デコレータの第一引数に関数を指定して、関数ラッパーを生成するコードと等価である。

@func_info
def add(param1, param2):
    return param1 + param2

 上記と以下のコードは等価である。

def add(param1, param2):
    return param1 + param2
add = func_info(add)

 デコレートされた関数を実行するということは、デコレータの関数ラッパー(_func_wrapper)に、ラップされる関数(add)の引数を渡して実行しているのと同じことである。

@func_info
def add(param1, param2):
    return param1 + param2
 
print add(1, 2)


実行結果:

--- func_info ---
func: <function add at 0x22f0230>
args: (1, 2) kwargs: {}
result: 3
-----------------
3


 デコレートされていない add1 関数の関数ラッパーを生成して、ラッパーに引数を渡して実行しても同じ結果が得られる。

def add1(param1, param2):
    return param1 + param2
 
# _func_wrapperを生成
print func_info(add1)
# _func_wrapperに引数(1, 2)を与えて実行
print func_info(add1)(1, 2)


実行結果:

<function _func_wrapper at 0xcff398>
--- func_info ---
func: <function add1 at 0xcff320>
args: (1, 2) kwargs: {}
result: 3
-----------------
3
  • python/decorator.1308482961.txt.gz
  • 最終更新: 2019/05/18 02:23
  • (外部編集)