Python-ステップアップ-アクセサリー小結


基本概念
具体的な概念は自分でgoogle
装飾器は1つのとても有名な設計モードで、いつも切面の需要があるシーンに用いられて、比較的に経典的なのは挿入ログ、性能テスト、事務処理、Web権限検査、Cacheなどがあります.
有名な例は、コーヒー、砂糖入りのコーヒー、牛乳入りのコーヒーです.本質的には、やはりコーヒーで、ただ元のものに「装飾」をして、いくつかの機能や特性を付加させただけです.
たとえばログを記録するには、いくつかの関数を記録する必要があります.
愚かな方法、すべての関数はコードを加えて、もしコードが変わったら、悲しくなります
装飾器の方法、1つの専門のログの記録の装飾器を定義して、必要な関数に対して装飾を行って、完成します
メリット
大量の関数から関数機能自体に関係のない同じコードを抽出し、再利用を継続する
すなわち、関数をまったく異なる動作に「修飾」することができ、ビジネスから権限と認証を独立させるなど、ビジネスロジックを効率的に直交分解することができます.
要約すると、装飾器の役割は、既存のオブジェクトに追加の機能を追加することです.
Pythonのアクセサリー
Pythonでは、アクセサリーが実現するのに便利です
なぜなら、関数は投げられるからです.
関数をオブジェクトとして使用します.
A.          ,       

B.             

def:
アクセラレータは関数をパッケージするための関数で、アクセラレータは関数の宣言が完了したときに呼び出され、呼び出し後に修正された関数オブジェクトを返し、元の識別子を再付与し、元の関数オブジェクトへのアクセスを永久に失う(宣言された関数は、アクセラレータによって装飾された関数に置き換えられる)
ある方法に装飾方法を適用すると,装飾関数名に参照される関数コードブロックエントリポイントが変更され,装飾方法によって返される関数エントリポイントが再指向される.
これによりdecoratorで既存の関数の機能を変更したり、さまざまな操作を追加したり、既存の実装を完全に変更したりすることができます.
分類:
装飾器は無パラメータdecoratorに分けられ、パラメータdecoratorがあります
*    decorator

           

*   decorator

    ,         ,            ,         

装飾器には参/無参、関数には参/無参の4種類があります
具体的な定義:
义齿
A.飾る方法を入力パラメータとして、
B.関数内で任意の操作が可能(威力が強く応用シーンが多いと想像できる)
C.最後に実行可能な関数が戻ってくることを確認すればよい(元の入力パラメータ関数であってもよいし、新しい関数であってもよい)
パラメータなし装飾–パッケージパラメータなし関数
パラメータの処理と最適化は不要
def decorator(func):
    print "hello"
return func
@decorator
def foo():
    pass
foo()

foo()は、
foo = decorator(foo)
foo()

パラメータなし装飾–パッケージパラメータ関数
def decorator_func_args(func):
def handle_args(*args, **kwargs): #         
    print "begin"
func(*args,**kwargs)   #    
    print "end"
    return handle_args
@decorator_func_args
def foo2(a,b=2):
    print a,b
foo2(1)

foo 2(1)は
foo2 = decorator_func_args(foo2)
foo2(1)

パラメータ付き装飾–パッケージパラメータなし関数
def decorator_with_params(arg_of_decorator):#         
    print arg_of_decorator
#        
    def newDecorator(func):
        print func
        return func
    return newDecorator
@decorator_with_params("deco_args")
def foo3():
    pass
foo3()

前との違いは、前のレイヤよりも1つ多くパッケージ化され、パラメータが先に伝達され、関数名が伝達されることです.
最初の関数decomakerは装飾関数で、そのパラメータは「装飾を強化する」ために使用されます.この関数は装飾された関数オブジェクトではないため、内部に少なくとも1つの装飾された関数を受け入れ、このオブジェクトに戻る必要があります(実際にはfoo 3=decorator_with_params(arg_of_decorator)(foo 3))
パラメータ付き装飾–パッケージパラメータ関数
def decorator_whith_params_and_func_args(arg_of_decorator):
    def handle_func(func):
        def handle_args(*args,**kwargs):
            print "begin"
            func(*args,**kwargs)
            print "end"
            print arg_of_decorator,func,args,kwargs
        return handle_args
    return handle_func
@decorator_whith_params_and_func_args("123")
def foo4(a,b=2):
    print "Content"foo4(1,b=3)

ビルトインクリーナー
内蔵の装飾器は3つあります:staticmethod,classmethod,property
class A():
    @staticmethod
    def test_static():
        print "static"
    def test_normal(self):
        print "normal"
    @classmethod
    def test_class(cls):
        print "class",cls
a = A()
A.test_static()
a.test_static()
a.test_normal()
a.test_class()

結果:
static
static
normal
class __main__.A

A.test_static
staticmethodクラスで定義されたインスタンスメソッドが静的メソッドになります
基本的に1つのグローバル関数と差は多くありません(selfを入力する必要はありません.一般的なパラメータのみです).ただし、クラスまたはクラスのインスタンスオブジェクトで呼び出すことができ、暗黙的にパラメータを入力することはありません.
静的言語での静的メソッドと同様
B.test_normal
≪一般オブジェクト・メソッド|General Objects Method|emdw≫:一般オブジェクト・メソッドには、クラス・オブジェクトのインスタンスを表すselfパラメータが少なくとも1つ必要です.
C.test_class
クラスで定義されたインスタンスメソッドがクラスメソッドになります
classmethodはクラスオブジェクトをインポートする必要があります.インスタンスとクラスオブジェクトで呼び出すことができます.
クラスまたはクラスインスタンスによって呼び出され、classオブジェクト(classではないインスタンスオブジェクト)を最初のパラメータとして暗黙的に入力できるclassに関連する方法です.
この方法はおかしいかもしれませんが、pythonのclassも静的言語でコンパイル中にしか存在しないタイプではなく、メモリに実際に存在するオブジェクトであることを明らかにすれば、やりやすいです.通常の方法は、クラスのインスタンスオブジェクトに関連する方法であり、クラスインスタンスオブジェクトによって呼び出され、そのインスタンスオブジェクトを最初のパラメータとして暗黙的に入力します.これも他の言語と比較されます.
D.区別
staticmethod,classmethodはグローバルメソッドに相当し,抽象クラスまたは親クラスで一般的に用いられる.一般的には具体的なクラスとは関係ありません.
クラスメソッドには追加のクラス変数clsが必要です.サブクラスが継承されている場合、呼び出しクラスメソッドが入力するクラス変数clsは親ではなくサブクラスです.
クラスメソッドと静的メソッドは、クラスオブジェクトとクラスのインスタンスオブジェクトからアクセスできます.
定義方法、入力パラメータ、呼び出し方法は異なります.
E.property
クラス属性の操作はjavaでgetter/setterを定義するのと同じです.
class B():
    def __init__(self):
        self.__prop = 1
    @property
    def prop(self):
        print "call get"
    return self.__prop
    @prop.setter
    def prop(self,value):
        print "call set"
        self.__prop = value
    @prop.deleter
    def prop(self):
        print "call del"
        del self.__prop

その他
A.アクセサリーの順番が重要なので注意が必要です
@A
@B
@C
def f():

に等しい
f = A(B(C(f)))

B.decoratorの作用対象はモジュールレベルの方法またはクラスの方法であることができる
C.functoolsモジュールは2つの装飾器を提供している.このモジュールはPython 2.5以降に追加されました.
functools.wraps(func)total_ordering(cls)というのは具体的に自分で見に行きましょう.
簡単な例です
変数を使用して、関数を呼び出すときに時間を統計するかどうかを制御します.
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#@author:[email protected]、
#@version: a test of decorator
#@date:20121027
#@desc:just a test
import logging
from time import time
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)is_debug = True
def count_time(is_debug):
    def handle_func(func):
        def handle_args(*args,**kwargs):
            if is_debug:
                begin = time()
                func(*args,**kwargs)
                logging.debug("[" + func.__name__ + "] -> " + str(time() - begin))
            else:
                func(*args,**kwargs)
        return handle_args
    return handle_func
def pr():
    for i in range(1,1000000):
        i = i * 2
        print "hello world"、
def test():
    pr()
@count_time(is_debug)
def test2():
    pr()
@count_time(False)
def test3():
    pr()
if __name__ == "__main__":
    test()
    test2()
    test3()

結果:
hello world
hello world
DEBUG:root:[test2] -> 0.0748538970947
hello world

The end!
変換元:http://wklken.sinaapp.com/