デコレーターの紹介:
Decorator (デコレーター) は、高度な Python 構文です。デコレーターは関数、メソッド、またはクラスを処理できます。 Python では、関数やクラスを処理するさまざまな方法があります。たとえば、Python クロージャでは、関数オブジェクトを特定の関数の戻り結果として認識します。他のメソッドと比較して、デコレータの構文はシンプルであり、コードは非常に読みやすいです。したがって、デコレータは Python プロジェクトで広く使用されています。
Decorator は Python 2.5 で初めて登場しました。元々は、関数やメソッドなどの呼び出し可能なオブジェクトを処理するために使用されていました (このようなオブジェクトは __call__ メソッドで定義されます)。 Python 2.6 以降の Python バージョンでは、クラスの処理にデコレータがさらに使用されます。
デコレーターは主に、ログの出力、関数のタイミング、ID 認証など、一般的に使用される関数の関数をラップするために使用されます。これを実現するためにデコレータを使用すると、プログラム全体の複雑さを軽減し、プログラム内のコードの量を減らすことができます。
これは実際には関数です。違いは、関数をパラメータとして受け取り、関数の代替バージョンを返すことです。
以下の簡単な例を見てください:
def add_number(func): def adder(arg): return func(arg)+100 return adder def f(x): return x f=add_number(f) print f(20)
add_number は、関数 (f) をパラメーターとして受け取り、元の関数に割り当てる別の関数 (adder) を返します。 、オリジナルのこの関数は、コードを追加せずに加算関数を実装します。
これはデコレーターのオリジナルの実装です。
しかし、この方法はまだ少し不便です。結局のところ、元の関数を再割り当てするために f=add_number(f) を使用します。
実際、次のメソッドを使用して、Python でのデコレータへの参照を簡素化できます。
def add_number(func): def adder(arg): return func(arg)+100 return adder @add_number def f(x): return x print f(20)
必要なのは単純な @add_numbe 呼び出しだけであり、非常に簡単で、基本的に元のコードに侵入することはありません。
さて、デコレーターとして毎回受け入れられるパラメータは関数と関数パラメータの 2 つだけですが、記述形式は基本的に同じであることに誰もが気づきました。この種の記述を簡略化する方法はありますか?
はい、Python にはデコレーターの作成を大幅に簡素化できるデコレーター パッケージが用意されています。
それで、3 番目の実装方法は次のとおりです:
from decorator import decorator @decorator def wrapper(func,arg): return func(arg)+100 @wrapper def f(x): return x print f(20)
ああ、それは本当に簡単です~
実際、上記の例はすべて 1 つのパラメーターを受け入れます。
例:
@decorator def wrapper(f,arg1,*args,**kwargs): print "I am just a wrapper~" return f(arg1,*args,**kwargs) @wrapper def f(arg1,*args,**kwargs): print arg1 for eacheArg in args: print 'non-keyword arg:',eacheArg for eachKw in kwargs.keys(): print 'keyword arg: %s:%d' % (eachKw,kwargs[eachKw]) args=('Joy','Steve') kwargs={"age":20} f('China',*args,**kwargs)
出力結果は次のようになります:
I am just a wrapper~ China non-keyword arg: Joy non-keyword arg: Steve keyword arg: age:20
*args と **kwargs の違いについては、どちらも可変長パラメーターを表すために使用できます。前者は Yuanzu で表されキー値を持たないのに対し、後者はキー値を持つ辞書であるという点だけです。両方を同じ関数で使用できますが、*args は **kwargs の前に指定する必要があります。
次の例のように:
def test_var_args_call(arg1, arg2, arg3): print "arg1:", arg1 print "arg2:", arg2 print "arg3:", arg3 args=(1,2,3) kwargs ={"arg1":"1","arg3": 3, "arg2": "2"} test_var_args_call(*args) print '-----------------' test_var_args_call(**kwargs)
どちらの実装効果も同じです。
最後の例は、関数の実行時間を表示することで関数を装飾することです
import time def log(func): def wrapper(*args, **kw): print '[%s] %s() was called...' % (time.ctime(),func.__name__) return func(*args, **kw) return wrapper @log def foo(): pass for i in range(4): foo() time.sleep(1)
出力結果は次のとおりです:
[Wed Jul 27 09:17:23 2016] foo() was called... [Wed Jul 27 09:17:24 2016] foo() was called... [Wed Jul 27 09:17:25 2016] foo() was called... [Wed Jul 27 09:17:26 2016] foo() was called...
上記は、ご質問がございましたら、メッセージを残してください。編集者がすぐにご返答いたします。また、PHP 中国語 Web サイトをサポートしていただきありがとうございます。
Python デコレータ関連の記事をより深く理解するには、PHP 中国語 Web サイトに注目してください。