首先咱們來看看什麼是個生成器,生成器本質就是迭代器python
在python中有三種方式來獲取生成器面試
1.經過生成器函數app
2.經過各類推到式來實現生成器函數
3.經過數據的轉換也能夠獲取生成器spa
首先,咱們先看一個很簡單的函數:指針
def func(): print(11) return 22 ret = func() print(ret) # 運行結果: 11 22
將函數中的return換成yield就是生成器code
運行的結果和上面的不同,爲何呢?? 因爲函數中存在yield,那麼這個函數就是一個生成器函數.對象
咱們在執行這個函數的時候.就再也不是函數的執行了.而是獲取這個生成器.如何使用???blog
想一想迭代器,生成器的本質就是迭代器.因此咱們能夠直接執行__next__()來執行如下生成器內存
那麼咱們能夠看到,yield和return的效果是同樣的,可是仍是有點區別
yield是分段來執行一個函數
return是直接中止這個函數
當程序運行完最後一個yield,那麼後面繼續運行__next__()程序會報錯
好了生成器咱們說完了.生成器有什麼做用呢?
咱們來看一下這個需求,老男孩向樓下賣包子的老闆訂購了10000個包子.包子鋪老闆實在一下就所有都作出來了
這樣作是沒有問題可是咱們目前這麼點人吃不完這麼多,只能先放到一個地方,要是可以我吃一個老闆作一個就完美了.
上下的區別: 第一種是直接把包子都拿來,很佔內存也就是很佔我們的位置,第二種使用生成器,想吃就拿一個.吃多少個包多少個.生成器是一個一個的,一直向下進行,不能向上.__next__()到哪,指針就指到哪兒.下一次繼續就獲取指針指向的值
接下來咱們再來認識一個新的東西,send方法
send和__next__()同樣均可以讓生成器執行到下一個yield
send和__next__()區別:
send 和 next()都是讓生成器向下走一次
send能夠給上一個yield的位置傳遞值,不能給最後一個yield發送值,在第一次執行生成器的時候不能使用send()
第一次調用的時候使用send()也能夠可是send的參數必須是None
生成器能夠for循環來循環獲取內部元素:
在python3中提供一種能夠直接把可迭代對象中的每個數據做爲生成器的結果進行返回
有個小坑,yield from 是將列表中的每個元素返回,因此 若是寫兩個yield from 並不會產生交替的效果
列表推導式
列表推導式生成器表達式以及其餘推導式,首先咱們先看一下這樣的代碼,給出一個列表,經過循環,想列表中添加1~10:
咱們換成列表推導式是什麼樣的,來看看:
列表推導式的常⽤寫法:
[結果 for 變量 in 可迭代對象]
列表推導式是經過⼀行來構建你要的列表, 列表推導式看起來代碼簡單. 可是出現錯誤之
後很難排查.
例. 從python1期到python17期寫入列表lst:
篩選模式
[結果 for 變量 in 可迭代對象 if 條件]
生成器表達式
這個其實就將列表推導式倆邊的中括號換成小括號就能夠了,咱們來看一下
print(l)的時候獲取到是:
生成器表達式也能夠進行篩選
生成器表達式和列表推導式的區別:
1. 列表推導式比較耗內存,一次性加載.生成器表達式幾乎不佔用內存.使用的時候才分配和使用內存
2. 獲得的值不同,列表推導式獲得的是一個列表.生成器表達式獲取的是一個生成器
舉個例子:
李大錘想吃雞蛋就上街買了一籃子的雞蛋放家裏,吃的時候拿一個吃的時候拿一個,這樣就是一個列表推導式,一次性拿夠佔地方.
王二麻子也想吃雞蛋,他上街卻買了一隻母雞回家.等他想吃的時候就讓母雞給下雞蛋,這樣就是一個生成器.須要就給你下雞蛋
生成器的惰性機制: 生成器只有在訪問的時候才取值,說白了.你找他要纔給你值.不找他要.他是不會執行的.
這是坑,必定要注意,生成器是要值的時候才能拿值,否則就沒有啦
字典推導式
根據名字應該也能猜到,推到出來的是字典
集合推導式
集合推導式能夠幫咱們直接生成一個集合,集合的特色;無序,不重複 因此集合推導式自帶去重功能
總結:
推導式有, 列表推導式, 字典推導式, 集合推導式, 沒有元組推導式
生成器表達式: (結果 for 變量量 in 可迭代對象 if 條件篩選)
生成器表達式能夠直接獲取到⽣成器對象. ⽣成器對象能夠直接進行for循環. ⽣成器具備惰性機制.
一個面試題,難度係數99999999課星
友情提示: 惰性機制,不到最後不會拿值