python中列表推導(dǎo)式與生成器表達(dá)式對比詳解
概述
Python中的列表推倒式(List Comprehension) 和 生成器表達(dá)式(Generator Expression)是兩種很相似的表達(dá)式,但含義卻不大不同,這里做一個(gè)對比。
列表推導(dǎo)式
列表推導(dǎo)式是比較常用的技術(shù),能將本來需要for loop 和 if else 語句的情況簡化成一條指令,最終得到一個(gè)列表對象:
even = [e for e in range(10) if e % 2 == 0]
具體細(xì)節(jié)不過多展開,相信很多使用Python的人都已經(jīng)足夠了解這種語法了。
需要注意的一點(diǎn)是,列表推導(dǎo)式不是惰性計(jì)算 ( Lazy Loading) 的,因此所有的列表成員都在聲明完語句后立即計(jì)算 (Eager Loading),因此在數(shù)組成員很多的情況下,速度會(huì)很慢,例如下面的在IPython環(huán)境里面的三個(gè)列表推導(dǎo)式的耗時(shí)統(tǒng)計(jì):
In [1]: %timeit even = [e for e in range(100000) if e % 2 == 0] 5.5 ms ± 24.8 μs per loop (mean ± std. dev. of 7 runs, 100 loops each) In [2]: %timeit even = [e for e in range(1000000) if e % 2 == 0] 58.9 ms ± 440 μs per loop (mean ± std. dev. of 7 runs, 10 loops each) In [3]: %timeit even = [e for e in range(100000000) if e % 2 == 0] 5.65 s ± 26.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
可以看到隨著元素個(gè)數(shù)的增加,列表推導(dǎo)式執(zhí)行的時(shí)間也相應(yīng)變長,占用的內(nèi)存也會(huì)變大。
有一種情況是,我們定義了很多很多的數(shù)組元素,但是最后并不是所有的元素都能用到,例如經(jīng)過幾條命令,最后可能只有列表里面的前10個(gè)元素會(huì)用到,或者只有符合某些條件的元素會(huì)用到,這樣的話,Eager模式就白白花費(fèi)了時(shí)間,白白花費(fèi)了內(nèi)存來創(chuàng)建很多用不到的元素,這顯然有很大的改進(jìn)空間。
生成器表達(dá)式
生成器能表達(dá)式解決上面的問題,它的元素迭代是惰性的,因此只有需要的時(shí)候才生產(chǎn)出來,避免了額外的內(nèi)存開銷和時(shí)間開銷: 生成器表達(dá)式不管元素?cái)?shù)目多大,創(chuàng)建時(shí)都是常數(shù)時(shí)間,因?yàn)樗]有立即創(chuàng)建元素。
那么生成器表達(dá)式的語法是怎么樣的呢,很簡單,只需要把列表推導(dǎo)式中的方括號改為圓括號:
even_gen = (e for e in range(10) if e % 2 == 0)
注意它的類型是生成器類型:
type(even_gen) # generator
創(chuàng)建生成器表達(dá)式的耗時(shí)統(tǒng)計(jì):
In [1]: %timeit even_gen = (e for e in range(100000) if e % 2 == 0) 376 ns ± 2.61 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each) In [2]: %timeit even_gen = (e for e in range(10000000) if e % 2 == 0) 382 ns ± 1.63 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each) In [3]: %timeit even_gen = (e for e in range(1000000000) if e % 2 == 0) 384 ns ± 2.85 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
可以看到隨著元素的增加,創(chuàng)建時(shí)間基本不變,而且比列表推導(dǎo)式的耗時(shí)要低不少。
使用場景選擇
那么是不是就是說使用中可以用生成器表達(dá)式替代列表推導(dǎo)式了呢,也不盡然,因?yàn)榱斜硗茖?dǎo)式得到的是一個(gè)列表,很多便捷操作(如slice等)可以作用到上面,而生成器表達(dá)式則不行:
In [17]: even = [e for e in range(10) if e % 2 == 0] In [18]: even[:3] Out[18]: [0, 2, 4] In [19]: even_gen = (e for e in range(10) if e % 2 == 0) In [20]: even_gen[:3] --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Input In [20], in <cell line: 1>() ----> 1 even_gen[:3] TypeError: 'generator' object is not subscriptable
而且兩者有一個(gè)致命的區(qū)別:生成器表達(dá)式只能迭代一次,而列表推導(dǎo)式可以使用很多次,舉例如下:
In [22]: even_gen = (e for e in range(10) if e % 2 == 0) In [23]: for e in even_gen: ...: print(e) ...: 0 2 4 6 8 In [24]: for e in even_gen: ...: print(e) ...:
可以看到生成器表達(dá)式在第二次迭代的時(shí)候,里面已經(jīng)沒有元素了!即第一次迭代已經(jīng)全部生成出來了,而列表推導(dǎo)式是每次迭代都是有相同的內(nèi)容:
In [25]: even = [e for e in range(10) if e % 2 == 0] In [26]: for e in even: ...: print(e) ...: 0 2 4 6 8 In [27]: for e in even: ...: print(e) ...: 0 2 4 6 8
因此總結(jié)來說,使用建議如下:
- 如果要多次迭代時(shí),建議使用列表推導(dǎo)式
- 如果數(shù)組很大或者有無窮個(gè)元素,建議使用生成器表達(dá)式
- 其他場景:兩者均可,自己看情況使用一個(gè),如果沒有速度和方便度的問題即可,如果有問題換另一個(gè)再試試
參考
總結(jié)
到此這篇關(guān)于python中列表推導(dǎo)式與生成器表達(dá)式對比的文章就介紹到這了,更多相關(guān)python 列表推導(dǎo)式和生成器表達(dá)式對比內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Python pandas讀取CSV文件應(yīng)該注意什么?
本文是給使用pandas的新手而寫,主要列出一些常見的問題,根據(jù)筆者所踩過的坑,進(jìn)行歸納總結(jié),希望對讀者有所幫助,需要的朋友可以參考下2021-06-06python實(shí)現(xiàn)excel讀寫數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了python操作EXCEL讀數(shù)據(jù)、寫數(shù)據(jù)的實(shí)例源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04Python的加密模塊md5、sha、crypt使用實(shí)例
這篇文章主要介紹了Python的加密模塊md5、sha、crypt使用實(shí)例,本文給出了MD5和crypt模塊的代碼實(shí)例,需要的朋友可以參考下2014-09-09Python?數(shù)據(jù)可視化超詳細(xì)講解折線圖的實(shí)現(xiàn)
數(shù)據(jù)可以幫助我們描述這個(gè)世界、闡釋自己的想法和展示自己的成果,但如果只有單調(diào)乏味的文本和數(shù)字,我們卻往往能難抓住觀眾的眼球。而很多時(shí)候,一張漂亮的可視化圖表就足以勝過千言萬語,讓我們來用Python實(shí)現(xiàn)一個(gè)可視化的折線圖2022-03-03python 實(shí)現(xiàn)將字典dict、列表list中的中文正常顯示方法
今天小編就為大家分享一篇python 實(shí)現(xiàn)將字典dict、列表list中的中文正常顯示方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07如何分離django中的媒體、靜態(tài)文件和網(wǎng)頁
這篇文章主要介紹了如何分離django中的媒體、靜態(tài)文件和網(wǎng)頁,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Python中內(nèi)置數(shù)據(jù)類型list,tuple,dict,set的區(qū)別和用法
這篇文章主要給大家介紹了Python中內(nèi)置數(shù)據(jù)類型list,tuple,dict,set的區(qū)別和用法,都是非常基礎(chǔ)的知識(shí),十分的細(xì)致全面,有需要的小伙伴可以參考下。2015-12-12