この記事では、Python のデコレーターとは何なのかについて説明します。 Python でのデコレータの紹介は一定の参考になるので、困っている友人は参考にしていただければ幸いです。
デコレーター、デコレーターは、本質的には、コードを変更せずに他の関数が機能できるようにする Python 関数です。 、デコレータの戻り値も関数オブジェクトです。
デコレータは、コア コードを変更することなく、コア コード部分の機能を強化します。たとえば、ログ、権限の検証、トランザクション処理、その他のシナリオを関数の前に挿入します。
また、関数関数とは関係のない大量の同様のコードを抽出して再利用できます。
Python の関数もオブジェクトとみなされ、それに割り当てることができます。変数 を指定し、その変数を介して関数を呼び出します。
例:
def foo(): print("2017-06-08") f = foo # 将函数赋值给变量,f为函数对象 f() # 返回结果: 2017-06-08
ここで、foo を拡張したいとします。 () 関数呼び出しの前にログを出力するなどの機能。ただし、foo() 関数の定義は変更したくありません。コードの実行中に機能を動的に追加するこの方法は、「デコレーター」と呼ばれます。
は次のとおりです。
def testfunc(func): print('testfunc') def wrapper(): print("%s %s() called" %(time.ctime(),func.__name__)) return func() return wrapper @testfunc def foo(): print('foo1()') foo() # 相当于执行testfunc(foo) ->wrapper(foo) -> foo()
実行結果:
testfunc Wed Sep 12 15:01:13 2018 foo() called foo1()
説明: foo() を実行する前に、まず testfunc(foo) を実行します。次に、wrapper() を実行し、戻り時に foo() 自体を呼び出します。
デコレータはパラメータを受け取ることができます。デコレータによって返された関数が呼び出されるとき、それはラッピング関数が呼び出され、パラメータがラッピング関数に渡され、ラッピング関数がパラメータを装飾関数に渡します。
は次のとおりです:
def testfunc_with_args(func): def wrapper_argus(arg1, arg2): print("I got args! Look:", arg1, arg2) func(arg1, arg2) return wrapper_argus @testfunc_with_args def full_name(first_name, last_name): # 带参数,将参数传给被装饰的函数 print("My name is", first_name, last_name) full_name("Peter", "Venkman") # 调用
実行結果:
I got args! Look: Peter Venkman My name is Peter Venkman
デコレータを呼び出す必要がある関数が複数あるが、関数のパラメータが異なる場合、どのように実装すればよいでしょうか? 1 つのデコレータに 1 つの関数が対応することはできません。現時点では、可変パラメータを持つデコレーターを使用して実装できます。
は次のとおりです:
def log(func): def wrapper(*args,**kwargs): # 可接受各种参数 print('call %s():'% func.__name__) return func(*args,**kwargs) # 返回一个函数 return wrapper # 装饰器返回一个函数,进入到wrapper() @log # @log放到now()的定义处,相当于执行语句:now = log(now) def now_1(a,b): print('now()1:a+b = ',a+b) @log def now_2(a,b,c): print('now_2():a+b+c = ',a+b+c) now_1(1,2) now_2(1,2,3)
実行してください~
関数に複数の関数を追加したい場合は、次のようにすることができます。マルチレイヤー デコレータの使用を検討してください。ただし、デコレータの実行順序に注意する必要があります。
クリを与える:
# 注意代码的执行顺序 def deco_1(func): print('------111111------') def wrapper(*args,**kwargs): # 包裹函数,参数与原函数的参数一致 print('start: this is deco_1.') func(*args,**kwargs) print('end: deco_1.') return wrapper # 返回值是一个包裹函数 def deco_2(func): print('------222222------') def wrapper(*args,**kwargs): print('start: this is deco_2.') func(*args,**kwargs) print('end: deco_2.') return wrapper @deco_1 @deco_2 def now_1(a,b): print('now()1:a+b = ',a+b) now_1(1,2)
実行結果:
# 结果,注意执行顺序: ------222222------ ------111111------ start: this is deco_1. start: this is deco_2. now()1:a+b = 3 end: deco_2. end: deco_1.
装飾関数パラメータ。デコレータ自体もパラメータを取ることができます。
def logging(level): def wrapper(func): def inner_wrapper(*args, **kwargs): print("[{level}]: enter function {func}()".format(level=level, func=func.__name__)) return func(*args, **kwargs) return inner_wrapper return wrapper @logging(level='INFO') def say(something): print("say {}!".format(something)) @logging(level='DEBUG') def do(something): print("do {}...".format(something)) say('hello') do("my work")
実行結果:
# 执行结果: [INFO]: enter function say() say hello! [DEBUG]: enter function do() do my work...
関連する推奨事項:
以上がPython のデコレータとは何ですか? Python のデコレータの概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。