標籤:mat 傳回值 一個 form 修改 int lis 核心 開始時間
## 產生器
- 產生器是用來建立Python序列的一個對象
- 通常產生器是為迭代器產生資料的
- 例如range()函數就是一個產生器
- 每次迭代產生器時,它都會記錄上一次調用的位置,並返回下一個值,這使程式不需要建立和儲存完整的序列
## 產生器函數
- 產生器函數與普通函數類似,但它的傳回值使用yield語句,而不是return
1 def my_range(start=0, last=10, step=1): 2 number = start 3 while number < last: 4 yield number 5 number += step 6 7 my_range # 是一個普通函數 8 # <function my_range at 0x7efe3dbf2e18> 9 10 my_range() # 返回一個產生器對象11 # <generator object my_range at 0x7efe3daac360>12 13 list(my_range(1, 10))14 # [1, 2, 3, 4, 5, 6, 7, 8, 9]
## 裝飾器
- 裝飾器的作用在於在不改變原有代碼結構的前提下,對原有代碼的功能進行補充擴充
- 裝飾器的本質上是接受函數為參數的高階函數,它把一個函數作為參數輸入並且返回一個功能拓展後的新函數
1 # 裝飾器函數,為函數添加兩條語句 2 def deco(fn): 3 def new_func(*args): # 內建函式的參數需要與傳入的fn的參數相同 4 print("執行函數:{0}".format(fn.__name__)) 5 result = fn(*args) 6 print("函數執行結果:{0}".format(result)) 7 return result 8 return new_func 9 10 11 @deco # 使用@裝飾函數名,使用裝飾器之後,add實際上已經指向了doco函數返回的新函數12 def add(*args):13 print("我是核心代碼,可不能改動我")14 result = 015 for n in args:16 result += n17 return result18 19 20 add(1, 2, 3, 4)21 """22 執行結果:23 執行函數:add24 我是核心代碼,可不能改動我25 函數執行結果:1026 """
- 一個函數可以有多個裝飾器
- 最靠近函數的裝飾器會先執行,然後一次向上執行裝飾器
1 def count_param(fn): 2 def new_func(*args): 3 amount = len(args) 4 fn(*args) 5 print("參數個數為:{0}".format(amount)) 6 return amount 7 return new_func 8 9 10 @count_param11 @deco12 def add(*args):13 print("我是核心代碼,可不能改動我")14 result = 015 for n in args:16 result += n17 return result18 19 20 add(1, 2, 3, 4)21 """22 執行結果:23 執行函數:add24 我是核心代碼,可不能改動我25 函數執行結果:1026 參數個數為:427 """
- 如果decorator本身需要傳入參數,那就需要編寫一個返回decorator的高階函數
1 import time 2 3 4 def log(now_time): 5 def deco(fn): 6 def new_func(*args, **kwargs): 7 print(now_time) 8 return fn(*args, **kwargs) 9 return new_func10 return deco11 12 13 @log(time.asctime(time.localtime(time.time())))14 def add(*args):15 print("我是核心代碼,可不能改動我")16 result = 017 for n in args:18 result += n19 return result20 21 22 add(1, 2, 3, 4)23 """24 執行結果:25 函數開始時間:Sun Jul 1 15:30:14 201826 我是核心代碼,可不能改動我27 """
- 此時列印add函數的__name__屬性探索:
print("核心函數名:{0}".format(add.__name__))"""輸出: 核心函數名:new_func"""
- 這表明雖然裝飾器表面上並沒有改變核心函數的內容,但實際上還是對核心函數的屬性進行了修改,所以還需要將核心函數的__name__屬性複製到新函數
1 import time 2 3 4 def log(now_time): 5 def deco(fn): 6 def new_func(*args, **kwargs): 7 # 將原函數的__name__屬性複製到新函數 8 new_func.__name__ = fn.__name__ 9 print(now_time)10 return fn(*args, **kwargs)11 return new_func12 return deco13 14 15 @log(time.asctime(time.localtime(time.time())))16 def add(*args):17 print("我是核心代碼,可不能改動我")18 result = 019 for n in args:20 result += n21 return result22 23 24 add(1, 2, 3, 4)25 print("核心函數名:{0}".format(add.__name__))26 """27 執行結果:28 Sun Jul 1 15:43:00 201829 我是核心代碼,可不能改動我30 核心函數名:add31 """
- 在functools裡面有一個專門的函數處理這個問題
1 import time 2 import functools 3 4 5 def log(now_time): 6 def deco(fn): 7 @functools.wraps(fn) # 在新的函數上添加裝飾器,修改新函數的__name__屬性 8 def new_func(*args, **kwargs): 9 print(now_time)10 return fn(*args, **kwargs)11 return new_func12 return deco13 14 15 @log(time.asctime(time.localtime(time.time())))16 def add(*args):17 print("我是核心代碼,可不能改動我")18 result = 019 for n in args:20 result += n21 return result22 23 24 add(1, 2, 3, 4)25 print("核心函數名:{0}".format(add.__name__))26 ”“”27 執行結果:28 Sun Jul 1 15:48:10 201829 我是核心代碼,可不能改動我30 核心函數名:add31 “”“
本文參考:
[美]Bill Lubanovic 《Python語言及其應用》
https://www.liaoxuefeng.com 廖雪峰的官方網站
Python產生器、裝飾器