python:decorator

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
python:decorator [2011/06/19 21:22] – [参考文献] ともやんpython:decorator [2020/02/25 11:14] (現在) – [参考文献] ともやん
行 14: 行 14:
     # 引数 func をラップする関数を定義     # 引数 func をラップする関数を定義
     @wraps(func)     @wraps(func)
-    def _func_wrapper(*args, **kwargs):+    def _func_info(*args, **kwargs):
         print '--- func_info ---'         print '--- func_info ---'
         print 'func:', func         print 'func:', func
行 25: 行 25:
         return result         return result
     # 引数 func をラップした関数を返却     # 引数 func をラップした関数を返却
-    return _func_wrapper+    return _func_info
  
 # デコレートされた関数を定義 # デコレートされた関数を定義
行 56: 行 56:
 def func_info(func): def func_info(func):
     # 引数 func をラップする関数を定義     # 引数 func をラップする関数を定義
-    def _func_wrapper(*args, **kwargs):+    def _func_info(*args, **kwargs):
         print '--- func_info ---'         print '--- func_info ---'
         print 'func:', func         print 'func:', func
行 67: 行 67:
         return result         return result
     # 引数 func をラップした関数を返却     # 引数 func をラップした関数を返却
-    return _func_wrapper+    return _func_info
 </code> </code>
- 上記のデコレータでは、引数の func 関数をラップした _func_wrapper 関数を返却している。+ 上記のデコレータでは、引数の func 関数をラップした _func_info 関数を返却している。
  
 ==== 関数のデコレート ==== ==== 関数のデコレート ====
- デコレータ式で add 関数をデコレートすると、add 関数は @func_info デコレータの _func_wrapper 関数ラッパーを返すようになる。+ デコレータ式で add 関数をデコレートすると、add 関数は @func_info デコレータの _func_info 関数ラッパーを返すようになる。
 <code python> <code python>
 @func_info @func_info
行 84: 行 84:
 実行結果: 実行結果:
 <code> <code>
-<function _func_wrapper at 0x22f02a8>+<function _func_info at 0x22f02a8>
 </code>\\ </code>\\
  デコレータ式は、デコレータの第一引数に関数を指定して、関数ラッパーを生成するコードと等価である。  デコレータ式は、デコレータの第一引数に関数を指定して、関数ラッパーを生成するコードと等価である。
行 102: 行 102:
  
 ==== デコレートされた関数の実行 ==== ==== デコレートされた関数の実行 ====
- デコレートされた関数を実行するということは、デコレータの _func_wrapper 関数ラッパーに、ラップされる add 関数の引数を渡して実行しているのと同じことである。+ デコレートされた関数を実行するということは、デコレータの _func_info 関数ラッパーに、ラップされる add 関数の引数を渡して実行しているのと同じことである。
 <code python> <code python>
 @func_info @func_info
行 120: 行 120:
 3 3
 </code>\\ </code>\\
- デコレートされていない add1 関数の関数ラッパーを生成して、ラッパーに引数を渡して実行しても同じ結果が得られる。+ デコレータを関数して実行する場合上記と等価なコドは以下のようる。
 <code python> <code python>
-def add1(param1, param2)+# func_info(addは _func_info を返すので 
-    u"""パラメータ1、2を加算した値を返しま。""" +以下は _func_info(1, 2) を実行しているのと等価 
-    return param1 + param2 +print func_info(add)(1, 2)
- +
-# _func_wrapperを生成 +
-print func_info(add1) +
-_func_wrapperに引数(1, 2)を与えて実行 +
-print func_info(add1)(1, 2) +
-</code>\\ +
-実行結果: +
-<code> +
-<function _func_wrapper at 0xcff398> +
---- func_info --- +
-func: <function add1 at 0xcff320> +
-args: (1, 2) kwargs: {} +
-result: 3 +
------------------ +
-3+
 </code> </code>
 ===== ドキュメンテーション文字列が失われないようにする(functools.wraps の使い方) ===== ===== ドキュメンテーション文字列が失われないようにする(functools.wraps の使い方) =====
行 149: 行 134:
 def func_info(func): def func_info(func):
     # 引数 func をラップする関数を定義     # 引数 func をラップする関数を定義
-    def _func_wrapper(*args, **kwargs):+    def _func_info(*args, **kwargs):
         print '--- func_info ---'         print '--- func_info ---'
         print 'func:', func         print 'func:', func
行 160: 行 145:
         return result         return result
     # 引数 func をラップした関数を返却     # 引数 func をラップした関数を返却
-    return _func_wrapper+    return _func_info
  
 @func_info @func_info
行 175: 行 160:
 説明: None 説明: None
 </code>\\ </code>\\
- この問題を解決するには、デコレータ内部の _func_wrapper の定義に @wraps を追加する必要がある。+ この問題を解決するには、デコレータ内部の _func_info の定義に @wraps を追加する必要がある。
 <code python> <code python>
 # -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
行 184: 行 169:
     # 引数 func をラップする関数を定義     # 引数 func をラップする関数を定義
     @wraps(func)     @wraps(func)
-    def _func_wrapper(*args, **kwargs):+    def _func_info(*args, **kwargs):
         print '--- func_info ---'         print '--- func_info ---'
         print 'func:', func         print 'func:', func
行 195: 行 180:
         return result         return result
     # 引数 func をラップした関数を返却     # 引数 func をラップした関数を返却
-    return _func_wrapper+    return _func_info
  
 @func_info @func_info
行 211: 行 196:
 </code> </code>
  
 +===== 引数を必要とするデコレータ =====
 + デコレータが引数を必要とする場合は、関数を二重にラップする必要がある。(ここでは inc_doc 引数を追加してみる。)
 +<code python>
 +# -*- coding: utf-8 -*-
 +from functools import wraps # python 2.5 以降で利用可能
 +
 +# 関数情報を表示するデコレータ
 +def func_info(inc_doc):
 +    def _func_info(func):
 +        # 引数 func をラップする関数を定義
 +        @wraps(func)
 +        def __func_info(*func_args, **func_kwargs):
 +            print '--- func_info ---'
 +            print 'func:', func
 +            if inc_doc:
 +                print 'doc:', func.__doc__
 +            print 'args:', func_args, 'kwargs:', func_kwargs
 +            # 引数 func を実行
 +            result = func(*func_args, **func_kwargs)
 +            print 'result:', result
 +            print '-----------------'
 +            # 引数 func の実行結果を返却
 +            return result
 +        # 引数 func をラップした関数を返却
 +        return __func_info
 +    # 引数 func をラップした関数を返却
 +    return _func_info
 +</code>
 + デコレータの引数(inc_docにTrue)を指定してデコレートする。
 +<code python>
 +# デコレートされた関数を定義
 +@func_info(True)
 +def add(param1, param2):
 +    u"""パラメータ1、2を加算した値を返します。"""
 +    return param1 + param2
 +
 +# デコレートされた関数を実行
 +print '関数実行->: add(1, 2)'
 +print add(1, 2)
 +</code>\\
 +実行結果:
 +<code>
 +関数実行->: add(1, 2)
 +--- func_info ---
 +func: <function add at 0x21ad500>
 +doc: パラメータ1、2を加算した値を返します。
 +args: (1, 2) kwargs: {}
 +result: 3
 +-----------------
 +3
 +</code>
 + デコレータを関数として実行する場合、上記と等価なコードは以下のようになる。
 +<code python>
 +# func_info(True) は _func_info を返すので
 +# func_info(True)(add) は _func_info(add) と等価
 +# _func_info(add) は __func_info を返すので
 +# 以下は __func_info(1, 2) を実行しているのと等価
 +print func_info(True)(add)(1, 2)
 +</code>
 ===== 参考文献 ===== ===== 参考文献 =====
-<html> +|<html> 
-<iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&bc1=FFFFFF&IS1=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=tomoyan596-22&o=9&p=8&l=as1&m=amazon&f=ifr&ref=tf_til&asins=4048686291" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe> +<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4048930613/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4048930613&linkCode=as2&tag=tomoyan.net-22&linkId=76a5d8652e69ddf7b93828d61c52b0b5"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4048930613&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=tomoyan.net-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=tomoyan.net-22&l=am2&o=9&a=4048930613width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> 
-</html>\\+</html>|<html> 
 +<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="https://rcm-fe.amazon-adsystem.com/e/cm?ref=tf_til&t=tomoyan.net-22&m=amazon&o=9&p=8&l=as1&IS2=1&detail=1&asins=4048930613&linkId=4991a49c3ce09cdb7570b40fe50a151c&bc1=ffffff&lt1=_top&fc1=333333&lc1=0066c0&bg1=ffffff&f=ifr"></iframe> 
 +</html>|
 [[http://www.python.jp/doc/2.6/library/functools.html|10.8. functools — 高階関数と呼び出し可能オブジェクトの操作 — Python v2.6.2 documentation]] [[http://www.python.jp/doc/2.6/library/functools.html|10.8. functools — 高階関数と呼び出し可能オブジェクトの操作 — Python v2.6.2 documentation]]
  • python/decorator.1308486160.txt.gz
  • 最終更新: 2019/05/18 02:23
  • (外部編集)