Pythonアクセサリー学習ノート
以前は<を見てdecoratorに出会ったときに霧の中で見ていましたが、それから多管にも行かず、後でこの問題に遭遇したときに解決しようと思っていました.今日Djangoコードを見てlogin_を見ましたrequiredなどの装飾器でまたこれに出会ったので、ネット上でいくつかのドキュメントを探して再学習し、ここでまとめました.
1.アクセサリーの意味
装飾器は有名な設計モデルで、断面的なニーズのあるシーンによく使われ、挿入ログ、パフォーマンステスト、トランザクションなどが古典的です.装飾器はこのような問題を解決する絶好の設計であり、装飾器があれば、多くの関数の中で関数機能自体に関係のない同じコードを抽出し、再利用を続けることができます.要約すると、装飾器の役割は、既存のオブジェクトに追加の機能を追加することです.
2.装飾文法
(1)無パラメータ装飾器
最初の関数decoは装飾関数であり、そのパラメータは装飾された関数オブジェクトである.伝達された関数オブジェクトをdeco関数内で「装飾」し、このオブジェクトに戻ることができます(
必ず戻ることを覚えて
ああ、そうでなければ、外でfooを呼び出す場所には関数がありません.実はこのときfoo=deco(foo)
(2)パラメータ付装飾器
被装飾関数パラメータなし
最初の関数decoは装飾関数であり、そのパラメータは「装飾を強化する」ために使用されます.この関数は装飾された関数オブジェクトではないため、内部に少なくとも装飾された関数を受け入れる関数を作成し、このオブジェクトに戻る必要があります.実際このときfoo=deco(argv)(foo)
被装飾関数にもパラメータがあります
まず5行目に注意し、この行を注釈するとfoo._name__これは「wrapper」で、この装飾器を使って装飾した後のfoo._name__元のfooか、wraps装飾器はfuncの一般的な属性をwrapper関数に与えた.また、この装飾器にはパラメータが付いていることにも気づいたと思います.実際には、assignedのプロパティ名は割り当てられた方法で置き換えられ、updatedのプロパティ名はupdateでマージされ、functoolsのソースコードを表示することでデフォルト値を得ることができます.この装飾器についてはwrapper=functoolsに相当する.wraps(func)(wrapper)
(3)マルチアクセサリーの組み合わせ使用
出力内容は次のとおりです.
deco_1 deco_2 __deco_2 __deco_1 test
関数testを宣言すると前の2行が出力され、実際に実行すると後の3行が出力されます.2つの装飾器は、注釈部分と同様に置き換えることができます.
(4)例
3.体得
複数の関数に重複コードがある場合、この部分のコードを個別に取り出して1つの装飾器に整理し、各関数に対して装飾器を呼び出すことで、コードの多重化を実現し、元の関数をより軽くすることができます.
また、パラメータの正当性をチェックするなど、複数の作成済み関数に共通の機能を追加する必要があります.パラメータの正当性を確認する必要がある関数ごとに呼び出しを出すと、各関数の内部修正を行わずに、正当性を確認する装飾器を単独で書くことができます.
参照先:
1.Pythonアクセサリー学習
2.Python装飾器とフェース向けプログラミング
1.アクセサリーの意味
装飾器は有名な設計モデルで、断面的なニーズのあるシーンによく使われ、挿入ログ、パフォーマンステスト、トランザクションなどが古典的です.装飾器はこのような問題を解決する絶好の設計であり、装飾器があれば、多くの関数の中で関数機能自体に関係のない同じコードを抽出し、再利用を続けることができます.要約すると、装飾器の役割は、既存のオブジェクトに追加の機能を追加することです.
2.装飾文法
(1)無パラメータ装飾器
def deco(func):
print("deco")
return func
@deco
def foo():
print("foo")
foo()
最初の関数decoは装飾関数であり、そのパラメータは装飾された関数オブジェクトである.伝達された関数オブジェクトをdeco関数内で「装飾」し、このオブジェクトに戻ることができます(
必ず戻ることを覚えて
ああ、そうでなければ、外でfooを呼び出す場所には関数がありません.実はこのときfoo=deco(foo)
(2)パラメータ付装飾器
被装飾関数パラメータなし
def deco(argv):
def decorator(func):
print("decorator")
return func
print("deco")
print(argv)
return decorator
@deco("123")
def foo():
print("foo")
foo()
最初の関数decoは装飾関数であり、そのパラメータは「装飾を強化する」ために使用されます.この関数は装飾された関数オブジェクトではないため、内部に少なくとも装飾された関数を受け入れる関数を作成し、このオブジェクトに戻る必要があります.実際このときfoo=deco(argv)(foo)
被装飾関数にもパラメータがあります
from functools import wraps
def deco(argv):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("wrapper")
return func(*args, **kwargs)
print("decorator")
return wrapper
print("deco")
print(argv)
return decorator
@deco("123")
def foo(data):
"this is foo"
print("foo")
print(data)
foo("afdasdf")
print(foo.__name__, foo.__doc__)
decorator関数の内部には、被装飾関数のパラメータを受け入れるための関数を定義する必要がある.このときfoo=deco(argv)(foo)(data)まず5行目に注意し、この行を注釈するとfoo._name__これは「wrapper」で、この装飾器を使って装飾した後のfoo._name__元のfooか、wraps装飾器はfuncの一般的な属性をwrapper関数に与えた.また、この装飾器にはパラメータが付いていることにも気づいたと思います.実際には、assignedのプロパティ名は割り当てられた方法で置き換えられ、updatedのプロパティ名はupdateでマージされ、functoolsのソースコードを表示することでデフォルト値を得ることができます.この装飾器についてはwrapper=functoolsに相当する.wraps(func)(wrapper)
(3)マルチアクセサリーの組み合わせ使用
def deco_1(func):
def __deco_1(*args, **kwargs):
print("__deco_1")
return func(*args, **kwargs)
print("deco_1")
return __deco_1
def deco_2(func):
def __deco_2(*args, **kwargs):
print("__deco_2")
return func(*args, **kwargs)
print("deco_2")
return __deco_2
@deco_2
@deco_1
def test():
print("test")
# test = deco_1(test)
# print(test)
# test = deco_2(test)
# print(test)
test()
出力内容は次のとおりです.
deco_1 deco_2 __deco_2 __deco_1 test
関数testを宣言すると前の2行が出力され、実際に実行すると後の3行が出力されます.2つの装飾器は、注釈部分と同様に置き換えることができます.
(4)例
def makebold(func):
def wrapped():
return "<b>" + func() + "</b>"
return wrapped
def makeitalic(func):
def wrapped():
return "<i>" + func() + "</i>"
return wrapped
@makebold
@makeitalic
def say():
return "Hello"
print(say())
#output
'''
<b><i>Hello</i></b>
'''
3.体得
複数の関数に重複コードがある場合、この部分のコードを個別に取り出して1つの装飾器に整理し、各関数に対して装飾器を呼び出すことで、コードの多重化を実現し、元の関数をより軽くすることができます.
また、パラメータの正当性をチェックするなど、複数の作成済み関数に共通の機能を追加する必要があります.パラメータの正当性を確認する必要がある関数ごとに呼び出しを出すと、各関数の内部修正を行わずに、正当性を確認する装飾器を単独で書くことができます.
参照先:
1.Pythonアクセサリー学習
2.Python装飾器とフェース向けプログラミング