Python の @decorator についての話
@ の使用に関しては、まずデコレータの概念について話さなければなりません
デコレータについて
公式ドキュメントの内容を見てみましょう。
デコレータは、ソフトウェア デザイン パターンに使用される名前です。デコレータは、サブクラスを直接使用したり、デコレートされる関数のソース コードを変更したりすることなく
、関数、メソッド、またはクラスの機能を動的に変更します。
パターンの名前。デコレータ直接サブクラス化したり、修飾される関数のソース コードを変更したりすることなく、関数、メソッド、またはクラスの機能を動的に変更できます。」 (Google 翻訳より)
Python におけるデコレータは、関数やメソッドの変更を容易にする Python 構文への特定の変更です。平たく言えば、デコレータは元の関数を変更せずに他の関数を追加することと同じです。たとえば、関数を使用するたびにマークとしてログを出力したいが、関数を直接変更したくない場合は、デコレーターが便利です。デコレーションとはその名の通り、ケーキに飾りを付けるという意味ですが、この例では「花」が丸太になっているのでしょう。
def triple_sum(a,b,c):
print( "the sum is ",(a+b+c))
#log修饰器
def log_dec(func):
def inner(a,b,c):
print("logloglog")
return func(a,b,c)
return inner
new_fun=log_dec(triple_sum)
new_fun(1,2,3)
として出力
ここには暗黙の事前知識ポイントもあります Python では、関数を変数として渡すことができます。
def triple_sum(a, b, c):
print( "the sum is ",(a+b+c))
new_func = triple_sum
new_func(123, 234, 345)
print(new_func.__name__)
関数に加えて、クラスもデコレータとしてラップできます。
class Cube(object):
def __init__(self, args):
self.args = args
def __call__(self, x, y):
res = self.args(x, y)
return res * res * res
# 这里Cube作为一个三次方的包装器,包装了一个普通的乘法函数
# 这里的乘法函数我用一个lambda表达式来略缩了
mul_nums = Cube(lambda x, y: x * y)
# 不使用lambda函数的话就是
#def mul_nums(x, y):
# return x * y
#mul_nums = Cube(mul_nums)
print(mul_nums)
print(mul_nums(4, 3))
小さな要約
つまり、デコレータとは実際には現在のモジュールに追加された新しい関数にすぎません。デコレータはクラスまたは関数にすることができます。設計手法の開閉原理に準拠した本来の機能自体は変わりません。
@(糖衣構文)について
@ は実際には Python の糖衣構文であり、@ を使用して上記の 2 つの例を変換します。
例 1:
def log_dec(func):
print("logloglog")
func(1,2,3)
@log_dec
def triple_sum(a,b,c):
print( "the sum is ",(a+b+c))
結果の出力は次のようになります:
Formula @ this 構文糖衣は
@Decorator 名はデコレータ名を置き換えます (装飾された関数)
つまり、triple_sum = log_dec(triple_sum)
例 2
@Cube
def mul_nums(x, y):
return x * y
同様に、@Cube は mul_nums = Cube(mul_nums) を置き換えます。
高度
デコレータの順序
既存の関数に追加する関数は、@ (コード ブロックの順序) よりも前に宣言する必要があることに注意してください。同時に、関数は複数のデコレータを同時に追加できます。
一番下の @ 関数から実行が開始され、その下の関数が入力として使用されます。印刷するとより鮮明に見えます
def log1(func):
print("log1log1log1")
def log2(func):
print("log2log2log2")
func(1, 2, 3)
@log1
@log2
def triple_sum(a, b, c):
print("the sum is ", (a + b + c))
出力は次のとおりです。実際の実行は、triple_sum = log2(triple_sum) Triple_sum = log1(triple_sum)
と同等です。
デコレータとパラメータ
1.パラメータを渡す
おそらくこれを見て Huadian を発見した盲目の学生もいるでしょう。 Triple_sum にパラメータを渡す方法! (上記の例の値はすべてハードコーディングされています) ここでデコレーターを変更します。
変換の前に、Python では関数をネストすることができます。
def func1():
print("I'm in func1")
def func2(msg):
print("I'm in func2")
print("I'm saying ",msg)
func2("hello")
func1()
関数のネストをクリアした後、デコレーターのパラメーターを変更する方法を見てみましょう。
def log1(func):
def wrapper(*args):
print("logloglog")
func(*args)
return wrapper
@log1
def triple_sum(a, b, c):
print("the sum is ", (a + b + c))
triple_sum(100,200,300)
関数のネストを使用して、デコレーターのパラメーターの受け渡しを完了します。
2. パラメータを使用したデコレータ
さらに、デコレータ自体もパラメータを運ぶことができます。さらにもう 1 レベル、関数のネストを使用します。
def log_with_args(arg1,arg2):
def log1(func):
def wrapper(*args):
print("logloglog")
func(*args)
print("arg1 is ",arg1,", args2 is ", arg2)
return wrapper
return log1
@log_with_args("hello","world")
def triple_sum(a, b, c):
print("the sum is ", (a + b + c))
triple_sum(111,222,333)
終わり
上記はデコレーターの内容全体です。コメント エリアで連絡や修正を歓迎します。
参考