生成器的本質就是迭代器,寫法和迭代器不同,用法同樣。app
獲取方法:函數
一、經過生成器函數spa
二、經過各類推導式來實現生成器3d
三、經過數據的轉換也能夠獲取生成器指針
例如:對象
更改return 爲 yield 即成爲生成器 該函數就成爲了一個生成器函數。再執行這個函數的時候,就再也不是函數的執行了,而是得到這個生成器。執行生成器能夠直接用__next__()來執行。blog
return和yield的區別:內存
yield是分段開執行一個函數,而return直接中止執行函數。for循環
當程序運行完最後一個yield。那麼後面繼續進行__next__()程序會報錯。變量
生成器的做用:
例如:
def cloth():
lst = []
for i in range(0,10000):
lst.append('衣服'+strt(i))
return lst
cl = cloth()
再看另外一種方式:
def cloth():
for i in range(0,10000):
yield'衣服'+str(i)
cl = cloth()
print(cl.__next__())
print(cl.__next__())
print(cl.__next__())
print(cl.__next__())
兩個案例的區別:第一種直接一次性所有拿出來,會很佔用內存。第二種使用生成器,一次就一個。用多少生成多少,生成器是一個一個的指向下一個。不會回去,__next__()到哪,指針就指到哪。下一次繼續獲取指針指向的值。
生成器函數:函數中帶有yield,執行生成器函數的時候返回生成器
生成器特色:
一、節省內存,幾乎不佔用內存。應用於數據量比較大、而單次使用不會用太多數據量的場合
二、惰性機制
三、只能往前
send 和__next__()的區別:
1.send 和next()都是讓生成器向下走一次。
2.send能夠給上一個yield的位置傳遞值,不能給最後一個yield發送值。在第一次執行生成器代碼的時候不能使用send()。
生成器可使用for循環來獲取內部的元素:
def func():
print(111)
yield 222
print(333)
yield 444
print(555)
yield 666
gen = func()
for i in gen:
print (i)
結果:
111
222
333
444
555
666
2、列表推導式,生成器表達式以及其餘推導式
一、列表推導式;
替換成列表推導式:
列表推導式是經過一行來構建須要的列表,看起來代碼簡單,但出現錯誤後很難排查。
推導式的經常使用寫法:
[結果 for變量 in 可迭代對象]
生成器表達式和列表推導式的語法基本上是同樣的。只是把[]替換成()。
打印的結果就是一個生成器。可使用for循環來循環這個生成器:
生成器表達式和列表推導式的區別:
a、列表推導式比較耗內存。一次性加載。生成器表達式幾乎不佔用內存。使用的時候才分配和使用內存。
b、獲得的值不同。列表推導式獲得的是一個列表。生成器表達式得到的是一個生成器。
生成器的惰性機制:生成器只有在訪問的時候才取值,即找他要纔給值,不找他要,是不會執行的。
深坑==>生成器,要值的時候纔拿值。
def func():
print(111)
yield 222
g = func() #此處生成一個生成器g
g1 = (i for i in g) # 生成器g1 數據來源於g
g2 = (i for i in g1) #生成器g2 來源於g1
print(list(g)) # 獲取g中的數據。這時func()纔會被執行。打印111獲取到222 g 獲值完畢。
print(list(g1)) #獲取g1中的數據。g1的數據來源是g,可是g已經取完了。g1也就沒有數據了。
print(list(g2))# 同g1
二、字典推導式:
例如:
在如下列表中,從lst1中獲取的數據和lst2中相對應的位置的數據組成一個新字典。
lst1 = ['jay','jj','sylar']
lst2 = ['周杰倫','林俊杰','邱彥濤']
dic = {lst[i]:lst2[i] for i in range(len(lst1))}
print (dic)
集合推導式:
集合推導式能夠幫咱們直接生成一個集合。集合的特色:無序,不重複。因此自帶去重功能。
總結:推導式有:列表推導式、字典推導式、集合推導式,沒有元組推導式。
生成器表達式:(結果 for 變量 in 可迭代對象 if條件篩選)
生成器表達式能夠直接獲取到生成器對象。生成器對象能夠直接進行for 循環 生成器具備惰性機制。