3.23
前のセクションを想起
* argsを、** kwargsから
-
*のArgs:* args引数に割り当てられた位置にある余分な引数について
-
** kwargsから、**余分なキーワード引数はkwargsからなるために割り当てられたディクショナリ
-
引数には、 *休憩
-
def index(*args,**kwargs): print(x,y) def wrapper(*args,**kwargs): # (1,2,34),{'x':1,'y':2} index(*args,**kwargs) # index(1,2,34,x=1,y=2) wrapper(1,2,34,x=1,y=2)
この形式では、引数の形式は、インデックスラッパーそのまま通話を渡します
名前空間とスコープ
- 関数のネストされた関係の名前空間の定義検出文法を決定する段階、すなわち
- Functionオブジェクト
- これは、別の関数の引数として機能することができ
- これは、関数の戻り値として使用することができます
ネストされた関数の定義
-
機能パッケージの機能
def outter(): def inner(): pass return inner # 不加括号,返回 inner的内存地址
閉鎖機能
-
機能を内蔵し、その外側の関数名を挙げ
def f1(): x = 1 y = 2 z = 3 f1()
F1のネームスペース通常の通話が清掃終了後、しかし、1つの名前が他の場所への参照である、と彼の参照がカウントその場合、彼の名前のスペースが回復されることはありません
モードを渡すパラメータ
-
パスの関数としての仮パラメータ値
-
値の関数として閉鎖体重の方法によって
def outter(x): def wrapper(): print(x) return wrapper # 处于局部 wrapper = outter(1) # 处于全局
-
名前空間:同じ名前の関数のグローバル機能割り当てにローカルが可能であるので、異なる名前空間には、同じ名前を使用することができます
本科
デコレーター
何ですか
-
ツール装置を指し、あなたは関数として定義することができます
-
装飾は、他のツールに機能を追加するために指し、
-
デコレーター:
ツールの定義(クラス、関数、現在唯一の機能は学ぶ)、別の関数に機能を追加するために使用
なぜあなたは使用しません
本来の機能の拡張のための実際の開発環境では、従うべきオープンクローズ原則を、ソフトウェアをオンラインで簡単にオンまたはオフに実行するように変更することはできません
オープンは閉じ:関数に新機能を追加したいのですが、この関数のソースコードを変更する必要はありません
- 開く:オープン機能を拡張します
- 休館:ソースコードを変更するために閉じられています
主導間違い、プログラム全体の誤差は、身体を起動する場合は、元の関数に新機能を追加し、それは、桁数を含むことができます。
デコレータは、装飾品によって改変し、元の関数に機能を追加するために、前提の下でソースコードを呼び出していません
どのように
例
def index(x,y):
print('index %s %s'%(x,y))
index(111,222)
正常な機能、この機能は現在、新しい機能を追加したいと思い、実行時間統計の機能があります
方法A:ソースコードを変更します
-
時間モジュールと
time.time
現在のタイムスタンプを返します。1970年から秒単位で現在の時刻に -
time.time前に関数を実行し、実行time.timeの終了後に、開始時間の減少関数終了時刻関数は、実行時間の関数であり、
import time def index(x,y): start = time.time() time.sleep(1) print('index %s %s'%(x,y)) end = time.time() print(end - start) index(111,222)
関数呼び出しを変更する方法はありません、機能を実装しますが、ソースコードを変更、オープンクローズドの原則を満たしていないん
方法2:追加のコール文の前と後
-
time.timeとのコールの前と後
import time def index(x,y): time.sleep(1) print('index %s %s'%(x,y)) start = time.time() index(111, 222) end = time.time() print(end - start)
呼び出しは、ソースコードを変更せずに達成するために、このコードの数行を追加する前と後の道の呼び出しを変更せずに、多くの場所で、すべての時間をカウントする必要がこの新しい機能を必要とするとき、あなたはいくつかの単語を書くために、これを繰り返す必要があります文は、コードが不適切、冗長です
ソリューション:デコレータ
-
利用機能コードの冗長性の問題を解決するための閉鎖が、(ラッパーになるために呼び出される)、およびインデックスが死ん111222書かれています
import time def index(x,y): time.sleep(1) print('index %s %s'%(x,y)) def wrapper(x,y): start = time.time() index(111, 222) end = time.time() print(end - start) wrapper()
-
1を改良し、ラッパーが死んで書き込みをしないでください
index(x,y) ... wrapper(111,222)
-
**、あなたが複数のパラメータ、渡すことができ、2改善された生きて書き込みパラメータを:
def index(x,y,z): ... def wrapper(*args,**kwargs): ... index(*args,**kwargs) wrapper(111,222,33,444)
-
改善された3:パラメータとして、ラッパー関数に渡す必要はなく、パラメータがこの機能に渡すことはできません:インデックスのみ装飾機能を優先、すべての機能は、ラッパーが欲しかった装飾することができる引数として関数にクロージャ機能の使用を、ライブ書くための機能
def outter(func): # 把要装饰的函数当作参数传给装饰器的包 def wrapper(*args,**kwargs): func(*args,**kwargs) return wrapper def index(x,y): print(x,y) f = outter(index) # 实际上是运行了wrapper,wrapper中的func实际上是调用时当作参数传入的函数 f(1,2)
ソースコードを変更せずに解決し、死んだ問題を記述するだけでなく、双方向通話を変更
-
決勝:道の呼び出しを変更しないでください
不正を犯し本来の機能の名前を持つ名前付きの改善機能
index = outter(index) index(1,2)
メソッドの概要
-
閉鎖機能を作った装飾機能
-
機能へのパッケージの装飾が施されたパラメータは、ネストされた関数を渡されます
-
閉鎖機能は、オブジェクト関数のパッケージ、受信したパラメータの本来の機能で飾られています
-
パッケージの機能は、ネストされた関数の関数を返します
-
詐欺を犯し、改名
index = outter(index) index()
本物:最終的な効果を達成するために、
このアプローチは、本来の機能を一度に問題が値を返しました:元の関数は、ラッパー関数に置き換えられている、インデックスを呼び出すことラッパーは値を返しませんが、ラッパを呼び出す実際には、する必要があり、元のラッパー関数の戻り値のリターンを許可します
最終的に向上
デコレータでは、元の関数から返される戻り値は、持っている必要があります
def outter(func): # 把要装饰的函数当作参数传给装饰器的包
def wrapper(*args,**kwargs):
func(*args,**kwargs)
res = func(*args,**kwargs)
return res # wrapper函数原函数的运行结果
return wrapper # 包函数在偷梁换柱的时候返回内嵌函数的函数体
def index(x,y):
print(x,y)
index = outter(index)
index(1,2)
最後に到達し、同じ方法、同じソースコードを呼び出し、戻り値は、実際のものを達成するために、同じです
シンタックスシュガー@デコレータ名
元の関数名に不正行為を犯しれるすべての装飾機能
-
index = outter(index) index(1,2)
この単純な構文上の文があります別の行に書き込みが装飾品の真上にあり@装饰器名字
、Pythonは自動的にあなたが不正を犯し与えます
-
def timmer(): # 装饰器必须在被装饰函数的上面 ... @timmer # 相当于帮你做了 index = timmer(index) def index(): ...
-
デコレータはデコレータの上に配置する必要があります、またはコード行@実行するために、デコレータまだ定義されていない、エラー
-
関数は、デコレータを複数重ね合わせてもよいです
ロード順:
@deco1 # deco1.wrapper的内存地址 = deco1(index) @deco2 # deco2.wrapper的内存地址 = deco2(index) @deco3 # deco3.wrapper的内存地址 = deco3(index) def index(): ...
概要
基本的なテンプレート
def outter(func):
def wrapper(*args,**kwargs):
res = func()
# 新功能
...
return res
return wrapper
@outter
def index(x,y):
# 原功能
...
index(x,y)
これは、テンプレートを取得している、元の関数は、インデックス、ラッパー書かれた新機能を書き込み、あなたは完全な引数なしのデコレータを取得します