python 裝飾器(複雜一點的)

裝飾器就是爲了在不改變函數代碼的狀況下爲函數添加新的功能app

實例函數

def note(func):
    "note function"
    print('note')
    def wrapper(x1,x2):
        "wrapper function"
        print(x1)
        print(x2)
        print('note something')
        # func(x1,x2)
        return func(x1,x2)

    return wrapper

@note   #test=note(test)
def test(a1,a2):
    "test function"
    print('I am test')


test(3,5)  #note(test)()
# print(test.__doc__)

 

帶參數的裝飾器,在普通裝飾器外邊再套一個函數,實現能夠傳遞額外參數
import time
def time_logger(flag=0):
    def show_time(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            end_time=time.time()
            print(end_time-start_time)

            if flag:
                print('將這個操做記錄到日誌中')
        return wrapper

    return show_time
@time_logger(1)
def add(*args,**kwargs):
    time.sleep(1)
    sum=0
    for i in args:
        sum+=i
    print(sum)

add(1,5,9)

多層裝飾器
裝飾器函數的執行順序分爲(被裝飾函數)定義階段和(被裝飾函數)執行階段
在被裝飾函數定義階段,執行順序是從最靠近函數的裝飾器開始,自內而外執行
在被裝飾函數執行階段,執行順序由外而內
須要注意的是,裝飾器函數在被裝飾器函數定義好的時候就當即執行了
def A(fn):
    print('執行A')
    def inner1():
        print('開始執行inner1')
        fn()
        print('結束inner1')
    return inner1

def B(fn):
    print('執行B')
    def inner2():
        print('開始執行inner2')
        fn()
        print('結束inner2')
    return inner2

@A
@B
def hello():   #A(B(hello))
    print('hello')

hello()

執行B
執行A
開始執行inner1
開始執行inner2
hello
結束inner2
結束inner1spa

 

類裝飾器
須要依靠類內部的__call__方法
import time
class Foo:
    def __init__(self,func):
        self.func=func
    def __call__(self, *args, **kwargs):
        start_time=time.time()
        self.func()
        end_time=time.time()
        print(end_time-start_time)
@Foo    #bar=Foo(bar)
def bar():
    print('bar')
    time.sleep(1)
bar()   #Foo(bar)()

 

functools.wraps,用於解決裝飾器的反作用
import functools
def foo():
    print('hello foo')
print(foo.__name__)
def C(func):
    # @functools.wraps(func)    能把原函數的原信息拷貝到裝飾器函數中,解決裝飾器的反作用
    def inner(*args,**kwargs):
        print(func.__name__+'!!!!!')
        return func(*args,**kwargs)
    return inner
@C
def cal(x):
    return x+x*x
print(cal(2))
print(cal.__name__)
# foo
# cal!!!!!
# 6
# inner  這時的cal.__name__變成裝飾器內部函數的名稱了
相關文章
相關標籤/搜索