生成器本質是迭代器,容許自定義邏輯的迭代器
迭代器和生成器區別:
迭代器自己是系統內置的,重寫不了.而生成器是用戶自定義的,能夠重寫迭代邏輯
生成器能夠用來鍾方式建立:
(1)生成器表達式(裏面是推導式 外面是圓括號)
(2)生成器函數 (用def定義,裏面含有yield)
#(1) 生成器表達式 generator
#[1,2,3,4] => [4,8,12,16]
#i<< 2 i乘以2的2次冪
gen = (i<<2 for i in range(1,5))
print(gen)
from collections import Iterable,Iterator
print(isinstance(gen,Iterator))
##(1)使用next進行調用生成器
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen )
print(res)
res = next(gen)
print(res)
#res = next(gen ) #StopIteration
#print(res) #越界
##(2)使用for循環調用生成器
gen = (i<<2 for i in range(1,5))
for i in gen:
print(i)
##(3)用for 和next 搭配調用生成器
gen = (i<<2 for i in range(1,5))
for i in range(2):
res = next(gen)
print(res)函數
(用def定義,裏面含有yield)
#yield相似於return
共同點在於: 執行到這句話都會把值返回出去
不一樣點在於: yield每次返回時,會記住上次離開時執行的位置,下次在調用生成器,會從上次執行的位置往下走
而return 直接終止函數,每次重頭調用
yield 6 和 yield(6) 2中寫法均可以 yield 6 更像 return 6 的寫法 推薦使用
from collections import Iterator,Iterable
#(1)基本使用
'''若是函數當中包含了yield,那麼這個函數是生成器函數'''
def mygen():
print("one")
yield 1
print("two")
yield 2
print("three")
yield 3
#初始化生成器函數 => 返回一個生成器對象,簡稱生成器
gen = mygen()
print(isinstance(gen,Iterator))
#調用生成器
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
#res = next(gen)
#print(res)
#代碼解析:
首先初始化生成器函數 返回生成器對象 簡稱生成器
經過next進行調用
第一次調用時候
print(one)
yield 1 記錄當前代碼執行的位置狀態,添加阻塞,暫停在這一行,並返回1,等待下一次調用
第二次調用時候
print(two)
yield 2 記錄當前代碼執行的位置狀態,添加阻塞,暫停在這一行,並返回2,等待下一次調用
第三次調用時候
print(three)
yield 3 記錄當前代碼執行的位置狀態,添加阻塞,暫停在這一行,並返回3,等待下一次調用
第四次調用時候
由於沒有yield返回值了 ,因此直接報錯..
#(2)優化代碼
def mygen2():
for i in range(1,101):
yield "個人球衣號%d" %(i)
#初始化生成器 返回生成器對象 簡稱生成器
gen2 = mygen2()
for i in range(50):
res = next(gen2)
print(res)
#(3) send 把值發送給一個yield
### send
#next 和 send 區別:
next只能取值
send不但能取值,還能發送值
#send注意點
第一個 send 不能給 yield 傳值 默認只寫None
最後一個yield 接受不到send 的發送值
#例:
def mygen():
print("start")
res = yield 1
print(res)
res = yield 2
print(res)
res = yield 3
print(res)
print("end")
#初始化生成器函數 返回生成器
send 在一次調用的時候,必須給參數None gen send(None)
是一個硬性要求的語法(由於第一次調用的時候,沒有遇到一個yield)
gen = mygen()
res = gen.send(None)
print(res)
res = gen.send(111)
print(res)
res = gen.send(222)
print(res)
# res = gen.send(333)
# # print(res)
#代碼解析:
第一個調用時,必須使用gen.send(None)
print(start)
res = yield 1記錄當前代碼執行的位置狀態,添加阻塞並返回1,等待下一次調用
第二次調用時,
send先發送,再返回,發送yield 1 res 接收到了111這個值
print(111)
res = yield 2 記錄當前代碼執行的位置狀態,添加阻塞並返回2 ,等待下一次調用
第三次調用時,
send先發送,再返回,發送yield 2 res接收到222這個值
print(222)
res = yield 3 記錄當前代碼執行的位置狀態 添加阻塞並返回3 ,等待下一次調用
第四次調用時,
由於沒有yield繼續返回了,直接報錯,越界錯誤
若是仍然想要執行後面沒有走完的代碼,好比95 96 ,那麼要經過try ...except 異常處理來解決優化
#異常處理格式:
try :
lst = [1,2]
print(lst[99])
execpt:
pass
### yield from :將一個可迭代對象變成一個迭代器返回spa
#例:
def mygen():
#yield ["陳桂濤","五金玲","張俊林"]
yield from ["陳桂濤","五金玲","張俊林"]
#初始化 一個生成器mygen 返回生成器
gen = mygen()
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
#用生成器寫斐波那契數列對象
#例:
# 1 1 2 3 5 8 13 21 ...
def mygen(n):
a = 0
b = 1
i = 0
while i< n:
#print(b)
yield b
a,b = b,a+b
i+=1
gen = mygen(10000)
for i in range(20):
res = next(gen)
print(res)three