一.生成器:python
生成器的實質就是迭代器app
在python中有三種方式獲取生成器:函數
1.經過生成器函數spa
2.經過各類推導式來實現生成器指針
3.經過數據的轉換也能夠獲取生成器code
二.經過生成器函數獲取生成器:對象
def func(): print('哈哈') yield '呵呵' #有yield就是生成器 ret = func() #經過函數來建立一個生成器即生成器函數被執行,獲取的是生成器,而不是函數的執行 print(ret) #返回的值是個地址就是個生成器 結果:<generator object func at 0x0000000000B99D00>
就是將函數中的return換成yield就是生成器,blog
return:直接返回結果,結束函數的調用內存
yield:返回結果,能夠讓函數分段執行.generator
1.如何執行生成器:
1)生成器的本質就是迭代器,因此能夠用__next__()進行執行
def func(): print('周杰倫') yield '昆凌' print('哈哈') yield '呵呵' ret = func() print(ret.__next__()) print(ret.__next__()) 結果:周杰倫 昆凌 哈哈 呵呵
注意:若是最後一個yield執行完畢,再次__next__()程序會報錯
生成器的做用:省內存,能夠一次去一個,一個個的指向下一個,不會回去,__next__()到哪,指針就指哪,下一次繼續獲取指針指向的值.
2.用send()方法:
def eat(): print('我吃什麼') a = yield '饅頭' print('a=',a) b = yield'大餅' print('b=',b) c = yield'韭菜盒子' print('c=',c) yield 'GAME OVER' gen = eat() #獲取生成器 print(gen.__next__()) print(gen.send('胡辣湯')) print(gen.send('狗糧')) print(gen.send('貓糧')) 結果:我吃什麼 饅頭 a= 胡辣湯 大餅 b= 狗糧 韭菜盒子 c= 貓糧 GAME OVER
send 和 __next__區別
1).send和next()都是讓生成器向下走一次
2).send能夠給上一個yield的位置傳遞值,不能給最後一個yield發送值,第一次執行生成器代碼的時候不能使用send()
3.生成器本質上是迭代器,因此能夠使用for循環取值
def func(): print('哈哈') yield '呵呵' print('嘿嘿') yield '嘻嘻' print('呀呀') yield'花花' ret = func() for i in ret: print(i)
4.能夠用列表list取值:
def func(): print('哈哈') yield '呵呵' print('嘿嘿') yield '嘻嘻' print('呀呀') yield'花花' ret = func() print(list(ret)) 結果:哈哈 嘿嘿 呀呀 ['呵呵', '嘻嘻', '花花']
三.列表推導式,生成器表達式以及其餘推導式
1)列表推導式:[結果 for 變量 in 可迭代對象 if 篩選]
例:給一個列表,經過循環,向列表中添加1-9
lst = [] for i in range(1,10) lst.append(i) print(lst)
經過列表推導式:
lst = [i = for i in range(1,10)] print(lst)
對列表中的數據進行篩選:[結果 for 變量 in 可迭代對象 if條件]
lst = [i fro i in range(1,101) if i%2 == 0] print(lst)
2)生成器表達式:
生成器表達式和列表推導式的語法基本上同樣,只是把[]替換()
gen = (i for i in range(100)) print(gen) 結果:<generator object <genexpr> at 0x0000000000A29D00>
打印結果是個生成器,能夠用for循環來獲取最終結果
gen = (i for i in range(100)) for i in gen: print(i)
生成器表達式也能夠進行篩選,跟列表表達式同樣,只是[]變成了()
生成器表達式和列表推導式的區別:
1.列表推導式比較耗內存,一次性加載,生成器表達式幾乎不佔內存,使用的時候才分配和使用內存.
2.獲得的值不同,列表推導式獲得的是一個列表,生成器表達式獲取的是一個生成器
生成器的惰性機制:生成器只有在訪問的時候才取值,說白了,你找他要他纔給你值,不找他要,他就不回執行.
def func(): print(111) yield 222 g = func() # 生成器g g1 = (i for i in g) # 生成器g1. 可是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同理
神坑:生成器,要值的時候纔拿值
3)字典推導式{結果 for 變量 in可迭代對象 if 篩選} 結果--->key:value
dic = {'a':'b','c':'d'}
把字典中的key和value互換
dic = {"a":"b", "c":"d"} new_dic = {dic[key]:key for key in dic } print(new_dic)
4)集合推導式:{結果 for 變量 in 可迭代對象 if 篩選} 結果--->key
集合推導式能夠直接生成一個集合,集合特別,無序,不重複,因此集合推導式自帶去重功能
lst = ["馬化騰", "馬化騰", "王建忠", "張建忠", "張建忠", "張雪峯", "張雪峯"] s = {i for i in lst} # 集合推倒式 print(s)
總結:推導式有:列表推導式,字典推導式,集合推導式,沒有元祖推導式
生成器表達式:(結果 for 變量 in 可迭代對象 if 篩選)
生成器表達式能夠直接獲取到生成器對象,生成器能夠直接進行for循環,生成器具備惰性機制