python中列表推導式和生成器的比較

列表推導式

優點:如果生成列表的方式不太複雜,這是建議使用列表推導式,其內部是通過cpython來實現的比較用for循環要快;列表推導式可以遍歷任意次。

缺點:一次性加載所有的數據到內存,不適合大量數據。

生成器

生成器可以使用yield關鍵字編寫也可以使用生成器表達式即把[]改成(),不會將所有的值一次性加載到內存中,延遲計算,一次返回一個結果,它不會一次生成所有的結果,這對大數據量處理,非常有用。

生成器遍歷數據只能遍歷一次。

下面舉列子說明。
在這裏插入圖片描述
從上面可以看出,生成相同數據量的列表,列表生成式所用的時間不到生成器的一半。這也是列表生成式的優點。

下面再看一下內存的佔用情況。
在這裏插入圖片描述
可以看到,生成器生成數據,但是increment都爲0,生成器的優點是省內存(生成器不會一次將所用的值返回,可以在需要的時候再取,因此不會有大量數據一直佔用內存。)

遍歷數據次數

生成器只能遍歷一次。

generator = (i for i in range(1,5))
print(next(generator))
print(next(generator))
for i in generator:
    print(i)
for i in generator:
    print(i)

1
2
3
4

列表可以無限遍歷

list1 = [i for i in range(1,5)]
print(list1[0])
print(list1[1])
print(list1[2])
for i in list1:
    print(i)
for i in list1:
    print(i)

1
2
3
1
2
3
4
1
2
3
4
爲什麼列表生成式會更快?

這是因爲,列表推導式被編譯後的字節碼執行速度更快。python當然不是一門編譯型語言,但是它還是要被解析成二進制的字節碼才能被執行,執行它的正是python解釋器。

通過dis模塊對原生的代碼分析,通過它,我們可以查看python代碼被編譯後的字節碼。

查看dis中的api的解釋,地址:https://docs.python.org/2/library/dis.html

  • dis.dis([bytesource])

btesource對象可以表示一個模塊、一個類、一個方法、一個函數或一個代碼對象。對於模塊,它分解了所有的函數。對於一個類,它分解所有的方法。對於單個代碼序列,它在每個字節碼指令中打印一行。如果沒有提供對象,它將分解最後一個回溯對象。

在這裏插入圖片描述
對比一下,不難發現,兩個段字節碼最大的區別在於添加元素的部分

func1 中,先要LOAD_ATTR,將append方法加載進來,然後CALL_FUNCTION,也就是執行

而在func2中,則直接調用了LIST_APPEND命令來添加元素,就是這一個小小的區別,使得列表推導式的速度會更快,因爲func1相比於func2多了一個LOAD_ATTR的過程,要明白,這條命令在每次循環中都會被執行,一旦循環的次數多起來,就必然拖慢速度。

參考:
https://www.jianshu.com/p/2244651d22a3
https://blog.csdn.net/jimmy_gyn/article/details/79142101
https://mp.weixin.qq.com/s/jiBmEb0DmMxPm5q2182rlw

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章