Python深さ05装飾器

10584 ワード

原文:
Python深さ05装飾器
作者:Vamei出典:http://www.cnblogs.com/vamei 転載を歓迎します.この声明も保留してください.ありがとうございます.
 
装飾器は高級なPython文法です.装飾器は、関数、方法、またはクラスを加工することができます.Pythonでは、関数とクラスを加工するための様々な方法があります.例えば、Python閉包では、関数オブジェクトをある関数として返します.他の方法に比べて、装飾器の文法は簡単で、コードの読み取り可能性が高いです.したがって、装飾器はPythonプロジェクトで広く使われています.
装飾器は最初にPython 2.5に出現し、関数や方法を加工するために最初に用いられたという起動可能なオブジェクト(callable object)を定義します.Python 2.6およびその後のPythonバージョンでは、装飾器はさらに加工類に用いられる.
 
装飾関数と方法
まず二つの簡単な数学関数を定義します.一つは二乗和を計算するために使われます.一つは二乗差を計算するために使われます.
# get square sum

def square_sum(a, b): return a**2 + b**2



# get square diff

def square_diff(a, b): return a**2 - b**2

print(square_sum(3, 4)) print(square_diff(3, 4))
基本的な数学機能を持った後、私たちは関数のために他の機能を追加したいかもしれません.関数を書き換えてこれを実現できます.
# modify: print input



# get square sum

def square_sum(a, b): print("intput:", a, b) return a**2 + b**2



# get square diff

def square_diff(a, b): print("input", a, b) return a**2 - b**2

print(square_sum(3, 4)) print(square_diff(3, 4))
関数の定義を変更して関数に機能を追加しました.
 
今、私達は装飾器を使って上記の修正を実現します.
def decorator(F): def new_F(a, b): print("input", a, b) return F(a, b) return new_F # get square sum

@decorator def square_sum(a, b): return a**2 + b**2



# get square diff

@decorator def square_diff(a, b): return a**2 - b**2



print(square_sum(3, 4)) print(square_diff(3, 4))
装飾器は、上のコードのようなdefの形で定義されてもよい.装飾器は、入力パラメータとして起動可能なオブジェクトを受信し、新しい起動可能なオブジェクトを返します.装飾器は新しいオブジェクト、つまり上のnew_を呼び出すことができます.Fです.new_Fでは、印刷機能を追加し、F(a,b)を呼び出して既存の関数の機能を実現しました.
装飾器を定義したら、私たちは@文法で使用できます.関数スクウェアsumとスクウェアdiff定義前に@decoratorを呼び出し、実際にスクウェアを使用します.sumまたはスクウェアdiffはdecoratorに渡され、decoratorが戻ってきた新しい呼び出し可能なオブジェクトを元の関数名(squaremusumまたはスクウェア)に割り当てます.ですから、私たちがスクウェアを呼んだらsum(3,4)の場合は、
square_sum = decorator(square_sum) square_sum(3, 4)
Pythonにおける変数名とオブジェクトは分離されていることを知っています.変数名は、任意のオブジェクトを指します.本質的には、装飾器は、変数名を再び指す役割を果たしています.同じ変数名を、新しく戻った呼び出し可能なオブジェクトに向けて指し示し、呼び出し可能なオブジェクトを修正する目的を達成します.
加工関数と似ていますが、装飾器加工の方法が使えます.
 
私たちが他の類似関数を持っているなら、関数を繰り返したり、新しいパッケージを追加したりすることなく、decoratorを呼び出し続けることができます.このようにして,プログラムの繰り返し利用性を向上させ,プログラムの可読性を増大させた.
 
参飾り器
上の装飾器の呼び出しでは、例えば@decoratorは、その後ろの関数が唯一のパラメータであるということを黙認しています.装飾器の文法では、私たちがdecoratorを呼び出すことができます.他のパラメータを提供します.このように、装飾器の編纂と使用のために、より大きな柔軟性を提供します.
# a new wrapper layer

def pre_str(pre=''): # old decorator

    def decorator(F): def new_F(a, b): print(pre + "input", a, b) return F(a, b) return new_F return decorator # get square sum

@pre_str('^_^') def square_sum(a, b): return a**2 + b**2



# get square diff

@pre_str('T_T') def square_diff(a, b): return a**2 - b**2



print(square_sum(3, 4)) print(square_diff(3, 4))
上のpre_strはパラメータを許容する装飾器です.これは実際に既存の装飾器の関数としてカプセル化され、装飾器に戻ります.環境パラメータを含む包みを閉じるとして理解できます.私達が@pre_を使う時str('^_^')を呼び出すと、Pythonはこの層のパッケージを発見して、装飾器の環境にパラメータを伝えることができます.コールは以下に相当します
square_sum = pre_str('^_^') (square_sum)
 
装飾類
上記の例では、装飾器は関数を受信し、加工関数の効果を発揮する関数を返します.Python 2.6以降、装飾器はクラスに展開されます.一つの飾り器は一つの種類を受信して、一つのクラスに戻ります.これによって加工類の効果があります.
def decorator(aClass): class newClass: def __init__(self, age): self.total_display = 0 self.wrapped = aClass(age) def display(self): self.total_display += 1

            print("total display", self.total_display) self.wrapped.display() return newClass @decorator class Bird: def __init__(self, age): self.age = age def display(self): print("My age is",self.age) eagleLord = Bird(5) for i in range(3): eagleLord.display()
decoratorの中で、私達は新しいクラスのnewClassを返しました.新しいクラスでは、元のクラスで生成されたオブジェクト(self.wrapped)を記録し、新たな属性total(u)を追加しました.displayは、呼び出し回数を記録するために使用されます.私たちもdisplay方法を同時に変更しました.
修正により、私達のBird類はdisplayを呼び出す回数を表示することができます.
 
締め括りをつける
飾り器の中心的役割はname bindingです.このような文法はPython多プログラムの範式のもう一つの表現です.ほとんどのPythonユーザーは装飾器を定義する必要はありませんが、装飾器を使用する可能性があります.装飾器がPythoonプロジェクトで広く使われていることから、この文法が非常に有益であることが分かります.
 
引き続き「Python高速教程」を読んでください.