Python実戦ウィジェット——装飾器
5819 ワード
Python装飾器の理解を簡単に述べ、簡単な装飾器を書きます.アクセサリーを理解するには、pythonの基礎知識をいくつか紹介します.1、役割ドメイン(ネーミングスペース)および変数の生存周期にプログラミングの基礎があることはすべて知っています.namespaceは:local namespace:現在の関数global namespaceに作用します.役割ドメインは現在のモジュールbuilt-in namespaceです.役割ドメインはすべてのモジュールpythonの各関数数に独自のネーミングスペースnamespaceを持っています.まず2つの小さなプログラムを見てみましょう:プログラム1:
出力は
プログラム2:
出力:
NO.2ではa_が見えますstringは2回定義された:関数func 1()に局所変数a_を定義するstringは、グローバル役割ドメインの同名変数a_を同時に非表示にします.string.これはpythonの特別な場所で、C/C++ではできません.NO.1とNO.2プログラムの実行結果からfunc 1()関数はまず自分のlocal namespaceで必要な変数を探すことがわかる.見つからない場合は、前のレベル:global namespaceで必要な変数を探します.すなわち、Pythonは、local namespace->global namespace->build-in namespaceの順にユーザーが必要とする要素を検索し、この要素を最初に見つけたnamespaceに準拠します.変数の生存周期は,関数が呼び出される開始に伴って始まり,呼び出しの終了に伴って終わる.2、関数のネストと関数パラメータpythonでネスト関数を許可し、関数で別の関数を定義することができます.次の例を参照してください.
出力:
func 1()で別の関数func 2():python解釈器はxというローカル変数を探す必要があります.検索に失敗した後も上位の役割ドメインで探し続けます.この上位の役割ドメインは別の関数で定義されています.
pythonでは、関数は他のものと同じようにオブジェクトです.関数を単純で一般的な数値と見なすことができます.関数は、パラメータとして別の関数に渡すこともできます.
出力:
上記のコードではfunc 3()関数には3つのパラメータがあり、そのうち1つ目は関数パラメータが入力されている.関数の名前は他の変数と同じように簡単な識別子にすぎません.
3、閉パッケージは奇妙な概念のように見えますが、抽象的には、非グローバルな役割ドメインにネストされた関数が定義されたときに存在する閉ネーミング空間を記憶できることを意味します.具体的には、次の例を見てみましょう.
出力:
非常に簡単なプログラムのように見えますが、その過程はよく理解しなければなりません.まずfunc 2()でx変数が呼び出され、そのローカルネーミングスペースでは検索されず、その後、前のレベルのネーミングスペースに移行してxの定義が見つかりました.しかし,変数の生存周期から見ると,xはfunc 1()の呼び出し開始に伴って始まり,func 1()終了時に終了する.変数xが既に存在しないため、func 1()が終了した後もfunc 2()を呼び出し続けることはできません.理論的に実行するとメモリエラーが発生します.しかし、事実はそうではなく、返されたfunc 2()は依然として仕事を続けることができる.ここでpythonの関数閉包概念を導入すると,func 1()で定義された関数はfunc 1()で必要な値を記憶できる(func 2()は必要ないためyがある場合は記憶されない).
上の3つを全部理解すれば、装飾器もわかりやすいです.装飾器は、関数をパラメータとして入力し、代替版の関数を返す閉パッケージです.
出力:
ここでfunc 1()は装飾器であり、func 3()をfunc 2()の装飾バージョンとして見ることができる.装飾器は関数本来の機能を変えて、とても良いツールと言えます.またpythonは、@識別子を使用して装飾器を関数に適用する簡単な表現も定義しています.関数の定義の前に@と装飾器の名前を付けるだけです.
2つのプログラムの出力は同じです.この用法を文法糖と呼び、装飾の行為をより直接的にすることができます.
a_string='LOVE'
def func1():
print a_string
func1()
print a_string
出力は
LOVE
LOVE
プログラム2:
a_string='LOVE'
def func1():
a_string='love'
print a_string
func1()
print a_string
出力:
love
LOVE
NO.2ではa_が見えますstringは2回定義された:関数func 1()に局所変数a_を定義するstringは、グローバル役割ドメインの同名変数a_を同時に非表示にします.string.これはpythonの特別な場所で、C/C++ではできません.NO.1とNO.2プログラムの実行結果からfunc 1()関数はまず自分のlocal namespaceで必要な変数を探すことがわかる.見つからない場合は、前のレベル:global namespaceで必要な変数を探します.すなわち、Pythonは、local namespace->global namespace->build-in namespaceの順にユーザーが必要とする要素を検索し、この要素を最初に見つけたnamespaceに準拠します.変数の生存周期は,関数が呼び出される開始に伴って始まり,呼び出しの終了に伴って終わる.2、関数のネストと関数パラメータpythonでネスト関数を許可し、関数で別の関数を定義することができます.次の例を参照してください.
def func1():
x=1
def func2():
print x
func2()
func1()
出力:
1
func 1()で別の関数func 2():python解釈器はxというローカル変数を探す必要があります.検索に失敗した後も上位の役割ドメインで探し続けます.この上位の役割ドメインは別の関数で定義されています.
pythonでは、関数は他のものと同じようにオブジェクトです.関数を単純で一般的な数値と見なすことができます.関数は、パラメータとして別の関数に渡すこともできます.
def func1(x, y):
return x + y
def func2(x, y):
return x - y
def func3(func, x, y):
print func(x,y)
func3(func1, 2, 1)
func3(func2, 2, 1)
出力:
3
1
上記のコードではfunc 3()関数には3つのパラメータがあり、そのうち1つ目は関数パラメータが入力されている.関数の名前は他の変数と同じように簡単な識別子にすぎません.
3、閉パッケージは奇妙な概念のように見えますが、抽象的には、非グローバルな役割ドメインにネストされた関数が定義されたときに存在する閉ネーミング空間を記憶できることを意味します.具体的には、次の例を見てみましょう.
def func1():
x=1
def func2():
print x
return func2()
a=func1()
出力:
1
非常に簡単なプログラムのように見えますが、その過程はよく理解しなければなりません.まずfunc 2()でx変数が呼び出され、そのローカルネーミングスペースでは検索されず、その後、前のレベルのネーミングスペースに移行してxの定義が見つかりました.しかし,変数の生存周期から見ると,xはfunc 1()の呼び出し開始に伴って始まり,func 1()終了時に終了する.変数xが既に存在しないため、func 1()が終了した後もfunc 2()を呼び出し続けることはできません.理論的に実行するとメモリエラーが発生します.しかし、事実はそうではなく、返されたfunc 2()は依然として仕事を続けることができる.ここでpythonの関数閉包概念を導入すると,func 1()で定義された関数はfunc 1()で必要な値を記憶できる(func 2()は必要ないためyがある場合は記憶されない).
上の3つを全部理解すれば、装飾器もわかりやすいです.装飾器は、関数をパラメータとして入力し、代替版の関数を返す閉パッケージです.
def func1(func):
print "1"
func()
print "3"
def func2():
print "2"
func3=func1(func2)
出力:
1
2
3
ここでfunc 1()は装飾器であり、func 3()をfunc 2()の装飾バージョンとして見ることができる.装飾器は関数本来の機能を変えて、とても良いツールと言えます.またpythonは、@識別子を使用して装飾器を関数に適用する簡単な表現も定義しています.関数の定義の前に@と装飾器の名前を付けるだけです.
def func1(func):
print "1"
func()
print "3"
@func1
def func2():
print "2"
2つのプログラムの出力は同じです.この用法を文法糖と呼び、装飾の行為をより直接的にすることができます.