1. 本質: 閉包函數python
2. 特色閉包
不修改已有函數的源代碼函數
不修改已有函數的調用方式spa
給已有函數增長額外的功能日誌
函數 + 實參高階函數 + 返回值高階函數 + 嵌套函數 + 語法糖 = 裝飾器code
函數和變量名一致, 都是一個名字對應內存地址中的一些內容blog
函數名 = 函數所在的內存地址內存
函數名() = 函數內存地址所表示的內容string
1 # 假設有代碼 2 x = 1 3 y = x 4 def func(): 5 print('hello') 6 test = z*2
1 improt time 2 3 def timer(func) 4 def deco(): 5 start = time.time() 6 func() 7 stop = time.time() 8 print(stop-start) 9 return deco 10 11 test = timer(test) 12 13 def test(): 14 time.sleep(2) 15 print("test is running!") 16 test()
1. 首先執行第11行代碼, 把test當成參數傳遞給timer()函數, 使得func = testit
2. 外部函數會返回deco, 傳遞給了test, 使得test = deco
3. 繼續執行語句, 跳過函數到了test(), 由於test地址等於deco, 因此test() = deco()
4. 進入內部函數def deco(), 因爲func = test, 因此func() = test()
5. 執行def test(), 完畢
裝飾器在裝飾時,須要在每一個函數前面加上''test = timer(test)''
咱們能夠用語法糖來表示 ---- @+裝飾器名稱--(函數名) @times
實際問題中, 每每函數是帶有參數的, 以下函數, 咱們將參數值只給予sum_num時, 就將會報錯
通過以上分析, 咱們知道sum_num = inner = fn, 因而得出sum_num() = inner() = fn(), 因此inner(), 和 fn()也必將傳遞同樣的參數
# 添加輸出日誌的功能 def logging(fn): def inner(num1, num2): print("--正在努力計算--") fn(num1, num2) return inner # 使用裝飾器裝飾函數 @logging def sum_num(a, b): result = a + b print(result) sum_num(1, 2)
咱們爲了將裝飾器變得更加有拓展性, 能夠給fn(), 和inner()函數傳遞不定長參數, 用於接收更大範圍的數據
1 # 添加輸出日誌的功能 2 def logging(fn): 3 def inner(*args, **kwargs): 4 print("--正在努力計算--") 5 result = fn(*args, **kwargs) 6 return result 7 8 return inner 9 10 11 # 使用語法糖裝飾函數 12 @logging 13 def sum_num(*args, **kwargs): 14 result = 0 15 for value in args: 16 result += value 17 18 for value in kwargs.values(): 19 result += value 20 21 return result 22 23 24 @logging 25 def subtraction(a, b): 26 result = a - b 27 print(result) 28 29 result = sum_num(1, 2, a=10) 30 print(result) 31 32 subtraction(4, 2)
帶有參數的裝飾器就是使用裝飾器裝飾函數的時候能夠傳入指定參數,語法格式: @裝飾器(參數,...)
在裝飾器外面再包裹上一個函數,讓最外面的函數接收參數,返回的是裝飾器,由於@符號後面必須是裝飾器實例。
1 # 添加輸出日誌的功能 2 def logging(flag): 3 4 def decorator(fn): 5 def inner(num1, num2): 6 if flag == "+": 7 print("--正在努力加法計算--") 8 elif flag == "-": 9 print("--正在努力減法計算--") 10 result = fn(num1, num2) 11 return result 12 return inner 13 14 # 返回裝飾器 15 return decorator 16 17 18 # 使用裝飾器裝飾函數 19 @logging("+") 20 def add(a, b): 21 result = a + b 22 return result 23 24 25 @logging("-") 26 def sub(a, b): 27 result = a - b 28 return result 29 30 result = add(1, 2) 31 print(result) 32 33 result = sub(1, 2) 34 print(result)