python生成器

列表生成式即List Comprehensions,是Python內(nèi)置的非常簡單卻強(qiáng)大的可以用來創(chuàng)建list的生成式赠制。
格式如下:

l1 = [x for x in range(10)]
print(l1)

結(jié)果如下:


列表生成器結(jié)果.jpg

通過列表生成式惯悠,我們可以直接創(chuàng)建一個列表躬络。但是蜡吧,受到內(nèi)存限制,列表容量肯定是有限的征绎。而且蹲姐,創(chuàng)建一個包含100萬個元素的列表,不僅占用很大的存儲空間人柿,如果我們僅僅需要訪問前面幾個元素柴墩,那后面絕大多數(shù)元素占用的空間都白白浪費(fèi)了。所以凫岖,如果列表元素可以按照某種算法推算出來拐邪,那我們是否可以在循環(huán)的過程中不斷推算出后續(xù)的元素呢?這樣就不必創(chuàng)建完整的list隘截,從而節(jié)省大量的空間扎阶。在Python中,這種一邊循環(huán)一邊計算的機(jī)制婶芭,稱為生成器:generator东臀。
創(chuàng)建 L 和 G 的區(qū)別僅在于最外層的 [ ] 和 ( ) , L 是一個列表犀农,而 G 是一個生成器惰赋。我們可以直接打印出L的每一個元素,但我們怎么打印出G的每一個元素呢呵哨?如果要一個一個打印出來赁濒,可以通過 next() 函數(shù)獲得生成器的下一個返回值:
下面采用生成器的方式創(chuàng)建列表:

ge = (x for x in range(4))
print(type(ge))
print(next(ge))
print(next(ge))
print(next(ge))
print(next(ge))
print(next(ge))

結(jié)果如下:


生成器next結(jié)果.jpg

生成器保存的是算法,每次調(diào)用 next(G) 孟害,就計算出 G 的下一個元素的值拒炎,直到計算到最后一個元素,沒有更多的元素時挨务,拋出 StopIteration 的異常击你。當(dāng)然,這種不斷調(diào)用 next() 實(shí)在是太變態(tài)了谎柄,正確的方法是使用 for 循環(huán)丁侄,因?yàn)樯善饕彩强傻鷮ο蟆K猿祝覀儎?chuàng)建了一個生成器后鸿摇,基本上永遠(yuǎn)不會調(diào)用 next() ,而是通過 for 循環(huán)來迭代它劈猿,并且不需要關(guān)心 StopIteration 異常拙吉。

ge = (x for x in range(10))
print(type(ge))
for i in ge:
    print(i,end=' ')

結(jié)果如下:


生成器結(jié)果.jpg

generator非常強(qiáng)大。如果推算的算法比較復(fù)雜糙臼,用類似列表生成式的 for 循環(huán)無法實(shí)現(xiàn)的時候庐镐,還可以用函數(shù)來實(shí)現(xiàn)。
通過之前的學(xué)習(xí)变逃,可以完成斐波那契數(shù)列的函數(shù)版必逆,代碼如下:

def fib(times):
    n = 0
    a, b = 0, 1
    while n < times:
        print(b, end=' ')
        a, b = b, a + b
        n += 1
    return 'done'


fib(5)

仔細(xì)觀察,可以看出揽乱,fib函數(shù)實(shí)際上是定義了斐波拉契數(shù)列的推算規(guī)則名眉,可以從第一個元素開始,推算出后續(xù)任意的元素凰棉,這種邏輯其實(shí)非常類似generator损拢。
也就是說,上面的函數(shù)和generator僅一步之遙撒犀。要把fib函數(shù)變成generator福压,只需要把print(b)改為yield b就可以了:

print()
print('*' * 15)


def fib(times):
    n = 0
    a, b = 0, 1
    while n < times:
        yield b
        a, b = b, a + b
        n += 1
    return 'over'


ret = fib(7)
for i in ret:
    print(i, end=' ')

結(jié)果如下:


斐波那契數(shù)列函數(shù)與生成器結(jié)果.jpg

如果用next調(diào)用掏秩,遇到y(tǒng)ield就會停止,所以同樣為了避免StopIteration異常荆姆,采用for循環(huán)遍歷蒙幻。在采用遍歷的時候,發(fā)現(xiàn)拿不到generator的返回值’over’胆筒。想要拿到返回值邮破,必須捕獲StopIteration異常,返回值包含在StopIteration的value中仆救。
關(guān)于生成器中的send的用法抒和,看如下代碼:

def fun():
    i = 0
    while True:
        i += 1
        print('...begin...')
        temp = yield i
        print('temp:%s'%temp)

ret = fun()
print(next(ret))
print('*'*10)
print(next(ret))
print('*'*10)
print(ret.send('haha'))

結(jié)果如下:

send結(jié)果.jpg

使用next()模擬多任務(wù)實(shí)現(xiàn)方式之一:協(xié)程

def test1():
    while True:
        print('...1...')
        yield None


def test2():
    while True:
        print('...2...')
        yield None


t1 = test1()
t2 = test2()

i = 0
while i < 3:
    t1.__next__()
    t2.__next__()
    i += 1

結(jié)果如下:

多任務(wù)結(jié)果.jpg

生成器是這樣一個函數(shù),它記住上一次返回時在函數(shù)體中的位置彤蔽。對生成器函數(shù)的第二次(或第 n 次)調(diào)用跳轉(zhuǎn)至該函數(shù)中間摧莽,而上次調(diào)用的所有局部變量都保持不變。生成器不僅“記住”了它數(shù)據(jù)狀態(tài)铆惑;生成器還“記住”了它在流控制構(gòu)造(在命令式編程中范嘱,這種構(gòu)造不只是數(shù)據(jù)值)中的位置。
生成器的特點(diǎn):
節(jié)約內(nèi)存员魏。迭代到下一次的調(diào)用時丑蛤,所使用的參數(shù)都是第一次所保留下的,即是說撕阎,在整個所有函數(shù)調(diào)用的參數(shù)都是第一次所調(diào)用時保留的受裹,而不是新創(chuàng)建的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虏束,一起剝皮案震驚了整個濱河市棉饶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌镇匀,老刑警劉巖照藻,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異汗侵,居然都是意外死亡幸缕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進(jìn)店門晰韵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來发乔,“玉大人,你說我怎么就攤上這事雪猪±干校” “怎么了?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵只恨,是天一觀的道長译仗。 經(jīng)常有香客問我抬虽,道長,這世上最難降的妖魔是什么古劲? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任斥赋,我火速辦了婚禮,結(jié)果婚禮上产艾,老公的妹妹穿的比我還像新娘。我一直安慰自己滑绒,他們只是感情好闷堡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疑故,像睡著了一般杠览。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纵势,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天踱阿,我揣著相機(jī)與錄音,去河邊找鬼钦铁。 笑死软舌,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的牛曹。 我是一名探鬼主播佛点,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼黎比!你這毒婦竟也來了超营?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤阅虫,失蹤者是張志新(化名)和其女友劉穎演闭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颓帝,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡米碰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了躲履。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片见间。...
    茶點(diǎn)故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖工猜,靈堂內(nèi)的尸體忽然破棺而出米诉,到底是詐尸還是另有隱情,我是刑警寧澤篷帅,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布史侣,位于F島的核電站拴泌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惊橱。R本人自食惡果不足惜蚪腐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望税朴。 院中可真熱鬧回季,春花似錦、人聲如沸正林。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽觅廓。三九已至鼻忠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杈绸,已是汗流浹背帖蔓。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞳脓,地道東北人塑娇。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像篡殷,于是被迫代替她去往敵國和親钝吮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Python列表生成式 列表推導(dǎo)式的一般語法 這種語法等價于以下代碼 下面舉一些列表推導(dǎo)式的栗子: Python中...
    So_ProbuING閱讀 1,275評論 0 0
  • 1.什么是生成器 通過列表生成式耳标,我們可以直接創(chuàng)建一個列表。但是邑跪,受到內(nèi)存限制次坡,列表容量肯定是有限的。而且画畅,創(chuàng)建一...
    一只寫程序的猿閱讀 938評論 0 4
  • 我們可以通過列表生成式簡單直接地創(chuàng)建一個列表砸琅,但是受到內(nèi)存限制,列表容量肯定是有限的轴踱。而且症脂,創(chuàng)建一個包含100萬個...
    PyChina閱讀 2,850評論 0 3
  • 1.生成器(generator)概念 生成器是迭代器,生成器提供了非常方便的自定義迭代器的途徑,在Python中,...
    Pello_Luo閱讀 787評論 0 0
  • 滾燙滾燙的金沙起了鹽漬飄了云三寸半的拉架布喝不了的水蓋不住的陽光 與索馬里為伍只有會笑的牙放空的頭顱只聽到浪拍沙大...
    蔣光頭jL94430閱讀 396評論 18 22