pythonの閉パッケージと装飾器

3310 ワード

クローズドパッケージ
閉包関数は2つの条件を満たす必要があります:1.関数内部で定義する関数2.グローバルな役割ドメインではなく外部の役割ドメインへの参照を含む
次のような閉包関数があります.
def callFunc():
    n = 1
    def show():
        print('show: ', n)
    return show

s = callFunc()
s()

プログラムが実行されると、callFunc関数は内部定義のshow関数を返し、show関数の内部に外部関数の変数を使用します.
show関数が返されると、現在の実行環境、すなわちshow関数で使用される外部変数nが保存される.
nはcallFunc関数のローカル変数であるため、通常はcallFunc関数の実行が終了すると、nは解放されます.
しかし、現在ではcallFunc関数にshow関数が返され、show関数は外部で再実行されるため、プログラムはshow関数に必要な実行環境を保存します.
この形式は閉鎖です.
デコレーション
装飾器自体も関数であり、既存の関数のために機能し、関数を変えずにいくつかの機能を増やして装飾する役割を果たす.
装飾器は実際には閉パッケージで定義された関数です
このデコレーション関数を使用する場合、デコレーションされた関数の前の行に@デコレーション関数名形式でデコレーションされます
import time

def count_time(func):
    def wrapper():      
        start = time.time()
        func()
        end = time.time()
        print('    :%s  '%(end - start)) 
    return wrapper

@count_time     
def my_count():
    s = 0
    for i in range(10000001):
        s += i
    print('sum : ', s)

my_count()

このような従来の関数機能を変えずに関数を拡張する形式を装飾器と呼ぶ.
@xxxを実行すると、実際には元の関数を閉パケットに渡し、元の関数の参照は閉パケットが返した装飾された内部関数の参照を指します.
装飾器のいくつかの形式:
  • 無パラメトリック無帰還値
  •  def setFunc(func):
            def wrapper():
                print('Start')
                func()
                print('End')
            return wrapper
    
        @setFunc
        def show():
            print('show')
    
        show()

    2.戻り値なし
    def setFunc(func):
            def wrapper():
                print('Start')
                return func()
            return wrapper
    
        @setFunc   # show = setFunc(show)
        def show():
            return 100
    
        print(show() * 100)

    3、パラメータの有無戻り値
    def setFunc(func):
            def wrapper(s):
                print('Start')
                func(s)
                print('End')
            return wrapper
    
        @setFunc   
        def show(s):
            print('Hello %s' % s)
    
        show('Tom')

    4、戻り値の参照
    def setFunc(func):
            def wrapper(x, y):
                print('Start')
                return func(x, y)
            return  wrapper
    
        @setFunc
        def myAdd(x, y):
            return  x + y
    
        print(myAdd(1, 2))

    万能装飾:
    被装飾関数の定義によって4つの形式が細分化されているが,学んだ技術を用いて,任意の形式関数定義に適した装飾器を実現できるだろうか.
    答えは肯定的で、可変パラメータとキーワードパラメータによって異なるパラメータタイプを受信します.
     def setFunc(func):
            def wrapper(*args, **kwargs):   #        
                print('wrapper context')
                return func(*args, *kwargs) #             
    
            return wrapper
    
        @setFunc
        def show(name, age):
            print(name,age)
    
        show('tom',12)

    類実現装飾形式:
    クラスの定義によって装飾器形式も実現できる.
    クラスで__を使用init__ および_call__方法で実現する
    class Test(object):
            #        ,                
            def __init__(self, func):
                self.__func = func
            #    __call__          
            def __call__(self, *args, **kwargs):
                print('wrapper context')
                self.__func(*args, **kwargs)
    
    
        #           call   
        @Test  # --> show = Test(show) show       ,       Test      
        def show():
            pass
    
    
        show()  #       ,          call,      

    クラス実装のアクセラレータは,アクセサリ関数の後,元の関数参照が関数ではなく,アクセサリクラスのオブジェクトである.