Pythonデコレーションを理解する
3127 ワード
Pythonデコレーションを理解する
Python装飾器はJavaの注釈に似ているように見えますが、ガチョウと注釈は違っていますが、同様に切断面向けのプログラミングができます。
Pythonの中の装飾器を理解するには、まずクローズドという概念を理解しなければならない。
包みを閉じる
ウィキペディアの解説を見てください。
コンピュータ科学では、クローズド(英語:Close)、またはクローズド(Lexical Cloure)または関数クローズド(function closures)は、自由変数を参照した関数である。この参照された自由変数はこの関数と共に存在し、作成された環境から離れても例外ではない。
公式の説明はいつも人の話をしません。but-talk is chap、show me the code:
この例を合わせてウィキペディアの説明を見れば、分かりやすくなります。クローズドとは、固有の変数の関数を参照して、この関数は実行されたコンテキストを保存しています。元のスコープから独立して存在します。
Pythonの中の飾りを見てみます。
飾り物
普通の装飾器は普通こうです。
呼び出し:
注目すべきは
パラメータ付き装飾器
装飾器はパラメータの入力を許可します。パラメータを持った装飾器は次のように3つの関数があります。
本来は同じです。
装飾器という文法は、Pythonの関数が第一公民であり、関数が対象であり、変数であり、パラメータとしてもよいし、戻り値としても良いし、非常に柔軟で強力であることを表しています。
Pythonには多くの関数式プログラミングの特性が導入されています。
Python装飾器はJavaの注釈に似ているように見えますが、ガチョウと注釈は違っていますが、同様に切断面向けのプログラミングができます。
Pythonの中の装飾器を理解するには、まずクローズドという概念を理解しなければならない。
包みを閉じる
ウィキペディアの解説を見てください。
コンピュータ科学では、クローズド(英語:Close)、またはクローズド(Lexical Cloure)または関数クローズド(function closures)は、自由変数を参照した関数である。この参照された自由変数はこの関数と共に存在し、作成された環境から離れても例外ではない。
公式の説明はいつも人の話をしません。but-talk is chap、show me the code:
# print_msg
def print_msg():
msg = "I'm closure"
# printer
def printer():
print(msg)
return printer
#
closure = print_msg()
# I'm closure
closure()
msg
は局所変数であり、print_msg
関数の実行後は存在しないはずである。しかし、ネスト関数はこの変数を参照して、この局所変数をネスト関数に閉じ込めると、閉じられたパケットが形成されます。この例を合わせてウィキペディアの説明を見れば、分かりやすくなります。クローズドとは、固有の変数の関数を参照して、この関数は実行されたコンテキストを保存しています。元のスコープから独立して存在します。
Pythonの中の飾りを見てみます。
飾り物
普通の装飾器は普通こうです。
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
return func(*args, **kwargs)
return wrapper
このようにして、方法名とそのパラメータを印刷する装飾器を定義します。呼び出し:
@log
def test(p):
print(test.__name__ + " param: " + p)
test("I'm a param")
出力:call test():
args = I'm a param
test param: I'm a param
装飾器は使う時に、@
文法を使って、困っています。実は、飾り器は一つの方法で、以下の呼び方と区別がありません。def test(p):
print(test.__name__ + " param: " + p)
wrapper = log(test)
wrapper("I'm a param")
@
文法は、関数を装飾器関数に導入するだけで、不思議なところがない。注目すべきは
@functools.wraps(func)
であり、これはpythonが提供する装飾器である。元関数のメタ情報を装飾器の中のfunc関数にコピーすることができます。関数のメタ情報には、docstring、name、パラメータリストなどがあります。@functools.wraps(func)
を除去してみてもいいです。test.__name__
の出力はwrapperになりました。パラメータ付き装飾器
装飾器はパラメータの入力を許可します。パラメータを持った装飾器は次のように3つの関数があります。
import functools
def log_with_param(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
print('log_param = {}'.format(text))
return func(*args, **kwargs)
return wrapper
return decorator
@log_with_param("param")
def test_with_param(p):
print(test_with_param.__name__)
このコードを見てまた疑問がありますか?内部層のdecorator関数のパラメータfuncはどうやって伝えられますか?上のような装飾器とは違いますね。本来は同じです。
@
文法を除いて、関数コールの形を回復して見れば分かります。# , decorator
decorator = log_with_param("param")
# test_with_param
wrapper = decorator(test_with_param)
#
wrapper("I'm a param")
出力結果は通常の飾り付けと同じです。call test_with_param():
args = I'm a param
log_param = param
test_with_param
これでは、飾り器というやや難解な特性も神秘的ではなくなった。装飾器という文法は、Pythonの関数が第一公民であり、関数が対象であり、変数であり、パラメータとしてもよいし、戻り値としても良いし、非常に柔軟で強力であることを表しています。
Pythonには多くの関数式プログラミングの特性が導入されています。