第六篇 生成器 ,生成器表示式,常見的內建函式
阿新 • • 發佈:2022-01-11
print(complex(1, 3)) # (1+3j) 數字 print(complex(111)) # (111+0j) 數字 print(complex('111')) # (111+0j) 當做字串處理
生成器
生成器就是一種自定義的迭代器
生成器物件
# 定義階段就是一個普通函式 def func(): print('first') yield 111 print('second') yield 222 print('third') # 報錯,丟擲異常 StopIteration 取到這裡就取乾淨了 ''' 當函式內出現yield關鍵字,再呼叫函式並不會觸發函式體程式碼的執行, 而是將函式變成了生成器(迭代器)''' # 呼叫函式:不執行函式體程式碼 而是轉換為生成器(迭代器) g = func() # print(g) # <generator object func at 0x7fca46cd2890> 生成器就是一種自定義的迭代器 res = next(g) # 每執行一個__next__程式碼往下執行到yield停止 返回後面的資料 print(res) res= next(g) # 再次執行__next__接著上次停止的地方繼續往後 遇到yield再停止 print(res) next(g) # 取不到了報錯 # 一出場就是一隻老母豬,可以存無窮個值的型別,但每次只能拿一個 def func(): res = 1 while True: yield res res += 1 g = func() # 得到一個迭代器 print(next(g)) # 列印next觸發程式碼執行,可以返回無數個值 print(next(g)) print(next(g))
自定義range功能
# fori in range(1, 10): # print(i) # 模仿上面的range() def my_range(start, stop): while start < stop: yield start start += 1 res = my_range(1, 10) # 呼叫函式:不執行函式體程式碼,而是轉換為生成器(迭代器) for i in my_range(1, 10): print(i) # 結果和range效果一樣 # 自定義range()模仿的更像一點 def my_range(start, stop=None, step=1): if not stop: # 解決一個引數 stop = start start = 0 while start < stop: # 解決二個引數 yield start start += step # 解決三個引數 # 一個數的情況 res = my_range(10) # 不執行函式體程式碼,而是轉換為生成器(迭代器) for i in res: print(i) # 兩個數的情況 res = my_range(1,10) for i in res: print(i) # 三個數的情況 res = my_range(1,10,3) for i in res: print(i)
yield傳值(瞭解)
def eat(name): print('%s 準備乾飯!!!'%name) while True: food = yield print('%s 正在吃 %s' % (name, food)) res = eat('jason') # 並不會執行程式碼,而是轉換成生成器 """ send與next作用相同,都是進行下一次迭代的意思(都會解阻塞yield關鍵字) send可以傳遞引數表示yield語句的返回值。而next不能傳遞引數 會先將引數當做yield語句的返回值,然後再解阻塞yield 遍歷。(因此不推薦第一次遍歷時使用send傳參) """ res.__next__() res.send('肉包子') # send的引數就是yield語句的返回值 res.send('蓋澆飯') ''' jason 準備乾飯!!! jason 正在吃 肉包子 jason 正在吃 蓋澆飯 '''
yield與return對比
-
yield
-
1.可以返回值(支援多個並且組織成元組)
-
2.函式體程式碼遇到yield不會結束而是"停住"
-
3.yield可以將函式 變成生成器 並且還支援外界傳值
-
4.yield可以返回值多次
-
-
return
-
1.可以返回值(支援多個並且組織成元組)
-
2.函式體程式碼遇到return直接結束
-
3. return只能返回值一次
-
生成器表示式
# 把列表生成式的[]換成()就是生成器表示式 res = (i for i in range(3)) print(res) print(next(res)) print(next(res)) print(next(res)) print(next(res)) # 報錯 """ 迭代器物件,生成器物件,我們都可以看成是"工廠" 只有當我們所要資料的時候工廠才會加工出"資料" 上述方式就是為了節省空間 """ # 統計一個檔案裡面的字元個數 with open('a.txt',mode='rt',encoding='utf-8') as f: res = f.read() print(len(res)) # 考慮到如果檔案過大一次讀嗎?可採用下面方式 # 方式一: res = 0 for line in f: # 每次統計一行,不費記憶體 res += len(line) print(res) # 方式二:利用內建函式sum,每取一次加一次 # res = sum((len(line) for line in f)) res = sum(len(line) for line in f) print(res) # 生成器表示式筆試題:求和 def add(n, i): return n + i # 呼叫之前是函式 呼叫之後是生成器 def test(): for i in range(4): yield i g = test() # 初始化生成器物件 for n in [1, 10]: g = (add(n, i) for i in g) """ 第一次for迴圈 g = (add(n, i) for i in g) 第二次for迴圈 g = (add(10, i) for i in (add(10, i) for i in g)) """ res = list(g) print(res) # A. res=[10,11,12,13] # B. res=[11,12,13,14] # C. res=[20,21,22,23] √ # D. res=[21,22,23,24]
常見內建函式
1.abs() 函式返回數字的絕對值
print(abs(123)) # 123 print(abs(-123)) # 123 print(abs(10.2)) # 10.2 print(abs(-10.2)) # 10.2
2.all() 用於判斷給定的可迭代引數中的所有元素是否都為True,如果是返回True,否則返回False
l = [11, 22, 33, 44] print(all(l)) # True l = [11, 22, 33, 0] # 元素除了是 0、空、None、False外都算True print(all(l)) # False l = [] # 注意:空元組、空列表返回值為True,這裡要特別注意。 print(all(l)) # True
3.any() 用於判斷給定的可迭代引數中的所有元素有一個為True,則返回True,否則返回False
l = [1, 2, 3] print(any(l)) # True l = [0, '', None, False] print(any(l)) # False
4.bin() 將int轉換成二進位制 oct() 將int轉換成8進位制 hex() 將int轉換成16進位制以字串形式表示
print(bin(123)) # 0b1111011 轉換成二進位制 print(oct(123)) # 0o173 將int轉換成8進位制 print(hex(123)) # 0x7b 將int轉換成16進位制
5.bytes() 將字串轉換成二進位制 str() 將二進位制轉換成字串(需指定編碼)
res = '哈哈哈' res1 = bytes(res, 'utf8') print(res1) # b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88' res2 = str(res1,'utf8') print(res2) # 哈哈哈 # 編碼 res1 = res.encode('utf8') # b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88' print(res1) # 解碼 res2 = res1.decode('utf8') # 哈哈哈 print(res2)
6.callable() 於檢查一個物件是否可呼叫的,可呼叫返回 True,否則返回 False
s = 'jason' print(callable(s)) # False def index(): pass print(callable(index)) # True
7.chr() 根據ASCII碼轉數字找字元 ord() 根據ASCII碼轉字元找數字
print(chr(65)) # A print(ord('Z')) # 90
8.complex() 將數字轉化為複數。如果第一個引數為字串,則不需要指定第二個引數
print(complex(1, 3)) # (1+3j) 數字 print(complex(111)) # (111+0j) 數字 print(complex('111')) # (111+0j) 當做字串處理
9.dir() 檢視當前物件可以呼叫的名字
print(dir()) # 獲得當前模組的屬性列表 print(dir([])) # 檢視列表的方法 def index(): pass print(dir(index)) # 檢視函式的方法
10.divmod() 把除數和餘數運算結果結合起來,返回一個包含商和餘數的元組(a // b, a % b)
print(dir()) # 獲得當前模組的屬性列表 print(dir([])) # 檢視列表的方法 def index(): pass print(dir(index)) # 檢視函式的方法
11.eval()只能識別簡單的語法 exec()可以識別複雜語法。都是將字串中的資料內容載入並執行
res1 = """ print('hello world') """ eval(res1) # hello world exec(res1) # hello world res = """ for i in range(10): print(i) """ # eval(res) # 複雜的無法識別 exec(res) # 可以看到結果
12.isinstance() 來判斷一個物件是否是一個已知的型別
print(isinstance(123, float)) # False print(isinstance(123, int)) # True print(isinstance(123, (str, int, list))) # 是元組中的一個返回True
13.pow() 方法返回 xy(x 的 y 次方) 的值
print(pow(2, 2)) # 4 print(pow(4, 3)) # 27
14.round() 方法返回浮點數x的四捨五入值
a = 4.6 print(round(a)) # 5 b = 4.5 print(round(b)) # 4 可以看成是五舍六入 c = 8.6 print(round(c)) # 9
15.sum() 方法對序列進行求和計算
l = [11, 22, 33, 44] print(sum(l)) # 110