裝飾器

 需求1:須要大長臉寫一個功能,測試一下同事二狗的函數的執行效率
import time #引入time模塊
print(time.time())

def func1():
    time.sleep(1)
    print('來了,老弟')

def func2():
    time.sleep(1)
    print('回手 掏 ,走位走位....')
#
#
import time
start_time = time.time()
func1()
end_time = time.time()
print('此函數的執行時間是%s' % (end_time-start_time))

import time
start_time = time.time()
func2()
end_time = time.time()
print('此函數的執行時間是%s' % (end_time-start_time))

# 初版本很差,重複造輪子,測試函數的效率 必須得複製代碼測試 改版:

# 第二版 將臉哥的代碼封裝到函數中,基本完成,
import time

def func1():
    time.sleep(0.6)
    print('來了,老弟')

def func2():
    time.sleep(0.5)
    print('回手 掏 ,走位走位....')

def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函數的執行時間是%s' % (end_time-start_time))
timmer(func1)
timmer(func2)

# 第三版  領導要求在生產環境測試函數的真正的執行效率:線上500個函數
# 線上問題:
    # 線上的函數你不改變
    # 函數的本來的調用方式不能改變
import time
def func1():
    time.sleep(0.6)
    print('來了,老弟')

def func2():
    time.sleep(0.5)
    print('回手 掏 ,走位走位....')

# 本來線上的調用方式:
# func1()
# func2()

# 可是用了臉哥的測試效率的函數以後
def timmer(f):
    start_time = time.time()
    f()
    end_time = time.time()
    print('此函數的執行時間是%s' % (end_time-start_time))

# 此時你已經改變了原函數的調用方式,而且程序執行了兩遍
func1()
timmer(func1)

# 第四版:第三版 沒有改變函數裏面的函數體,可是改變了函數的調用方法,因此要解決:用最少的代碼,解決調用方式一致性的問題。
# 最終完成的需求 func1() 這個指令既要執行func1函數,又要測試效率
import time
def func1():
    time.sleep(0.6)
    print('來了,老弟')
#
# def func2():
#     time.sleep(0.5)
#     print('回手 掏 ,走位走位....')

def timmer(f): # f = func1 函數的內存地址
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函數的執行時間是%s' % (end_time-start_time))
    return inner
func1 = timmer(func1) # = inner
func1()  # inner()

# 第五版: 最終基礎版 python提供一個機制,優化,語法糖 @  上面仍是不夠優化,咱們引入第5種python語法糖@   示例:func1 = timmer(func1) 就等於@timmer
import time
def timmer(f):  # f = func1 函數的內存地址
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print('此函數的執行時間是%s' % (end_time - start_time))

    return inner

@timmer # func1 = timmer(func1)
def func1():
    time.sleep(0.6)
    print('來了,老弟')

func1()  # inner()
@timmer
def func2():
    time.sleep(0.6)
    print('來le')
func2()

@timmer
def func3():
    time.sleep(0.6)
    print('')
func3()

2、被裝飾函數帶參數

import time
def timmer(f):  # f = func1或者func2 函數的內存地址
    def inner(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        print('此函數的執行時間是%s' % (end_time - start_time))

    return inner

@timmer # func1 = timmer(func1) 在某個函數的上面加上這個
def func1(a):
    time.sleep(0.6)
    print('來了,%s' % (a))
func1('alex')

@timmer  # func2 = timmer(func2)
def func2(c,d):
    time.sleep(0.6)
    print('%s 年齡 %s' % (c,d))
func2('二狗',21)

3、被裝飾函數帶返回值

import time
def timmer(f):  # f = func1 函數的內存地址
    def inner(*args, **kwargs):
        start_time = time.time()
        ret = f(*args, **kwargs)
        end_time = time.time()
        print('此函數的執行時間是%s' % (end_time - start_time))
        return ret

    return inner
@timmer  # func1 = timmer(func1)
def func1(a):
    time.sleep(0.6)
    print('來了,%s' % (a))
    return 666
print(func1('alex'))  # print(inner('alex'))

 

總結:python

一、裝飾器本質其實閉包,
二、裝飾器在不改變原函數的內部函數體以及調用方式的前提下,給函數增長了額外的功能:登陸,註冊,打印日誌,函數效率等等。

4、手寫裝飾器

# 手寫裝飾器1,先寫閉包:
def wrapper(f):
    def inner():
        f()
    return inner

# 手寫裝飾器2,增長參數:
def wrapper(f):
    def inner(*args,**kwargs):
        f(*args,**kwargs)
    return inner
# 手寫裝飾器3,增長返回值ret,增長函數部分:

def wrapper(f): def inner(*args, **kwargs): ''' 執行被裝飾的函數以前的操做''' print('執行以前', 555) #示例 ret = f(*args, **kwargs) print('執行以後', 666) #示例 ''' 執行被裝飾的函數以後的操做''' return ret return inner @wrapper def func1(): pass func1()

相關文章
相關標籤/搜索