1 問題描述
請設計一個裝飾器,它可以作用於任何函數上,打印函數執行時間
import time
def metric(fn):
start_time = time.time()
end_time = time.time()
print('耗時:{:.4f}s'.format(end_time - start_time))
return fn
2 解題提示
本題是對裝飾器的練習
- 裝飾器參考第二節內容 繼承和多態、@property、裝飾器
- 時間模塊的導入 使用 import語句
- 定義兩個變量用來接收函數開始的時間,結束時的時間
- 兩個變量進行相減計算出函數運行的時間
- 使用f._ _name _ _ 來傳遞要測量時間的函數的函數名
3 評分標準
- 本題共計30分,實現裝飾器20分
- 輸出函數執行的時間 5分
- 代碼註釋、格式5分
4 要點解析
4.1 * 與 ** 參數
動態參數的表示,有時候我們要傳入參數的數目不確定,這時候就需要用到動態參數。主要作用,就是擴展函數的功能
- *代表要把傳入的參數轉爲一個元組,
- **代表要把傳入的參數轉爲一個字典。
def func_1(*args):
print (args)
func_1(1,2,3,4,5,[1,3,5,7])
# 輸出:(1, 2, 3, 4, 5, [1, 3, 5, 7])
def func_2(**kwargs):
print (kwargs)
func_2(k1=1,k2=2,k3=3)
# 輸出:{'k1': 1, 'k2': 2, 'k3': 3}
def fun_3(arg,*args,**kwargs):
print(arg,args,kwargs)
fun_3(6,7,8,9,a=1, b=2, c=3)
# 輸出:6 (7, 8, 9) {'a': 1, 'b': 2, 'c': 3}
4.2 推導式與三元表達式
# 將奇數取出,作爲一個新的列表
# 一般方式
lst = [1,2,3,4,5,6,7,8]
new_lst = []
for i in lst:
if i %2==1:
new_lst.append(i)
print(new_lst)
# 推導式
lst = [1,2,3,4,5,6,7,8]
new_lst = [i for i in lst if i%2==1]
print(new_lst)
# 三元表達式
a=7
b=7
a=a-2 if a>6 else 2
print(a)
b=b-2 if a>8 else 2 # 如果滿足條件,b=b-2,不滿足 輸出 else後面的
print(b)
4.3 裝飾器概念
- 定義:python裝飾器本質上就是一個函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外的功能
- 應用場景:引入日誌,函數執行時間的統計,執行函數前的準備工作,執行函數後的處理工作,權限校驗,緩存等
- 語法規則:在原有的函數上加上 @符,裝飾器會把下面的函數當作參數傳遞到裝飾器中,@符又被成爲 語法糖
def m(n):# 裝飾函數
print(n)#現在的形參n==被裝飾的函數
def nb():# 被裝飾
print('***************')#我在傳入的函數執行之前做一些操作
n()# 執行函數
print('***************')#我在目標函數執行後再做一些事情'
return nb#【1】返回nb函數名
# 自動將其下面的函數作爲參數傳到裝飾函數中去
@m
# 被裝飾函數
def ych():
print('裝飾器')
ych()
4.4 帶參裝飾器
def m(n):# 裝飾函數
def nb(a):# 被裝飾
print('***************')#我在傳入的函數執行之前做一些操作
n(a)# 執行函數
print('***************')#我在目標函數執行後再做一些事情'
return nb#【1】返回nb函數名
# 自動將其下面的函數作爲參數傳到裝飾函數中去
@m
# 被裝飾函數
def ych(name):
print('今天是{}的生日'.format(name))
ych('zs')
def ych(name,age):
print('今天是{}的{}歲生日'.format(name,age))
ych('ls',18)
4.5 雙層裝飾器
def m(n):
def nb(c):
print('***************')
n(c)
print('***************')
return nb
def k(n):
def nb(c):
print('###############')
n(c)
print('###############')
return nb
@k
@m
def ych(name):
print(name,'開演唱會')
ych('劉德華')
5 代碼實現
# 導入時間模塊
import time
# 裝飾函數
def computer_runtime(func):
# 把run方法擴展功能之後的新方法
def wrapper(*args,**kwargs):
# 函數開始時間
start = time.time()
# 調用函數
func()
# 結束時間
end = time.time()
print('%s執行了%f 秒' % (func.__name__, end - start))
# 回調裝飾函數
return wrapper
#語法糖
@computer_runtime
# 被裝飾函數
def run():
time.sleep(1)
l = [x**2 for x in range(1000)]
run()