眾所周知,Python串列推導的作業原理比回圈要快,但是,在某些情況下,它們可能會嚴重破壞程式的性能,甚至導致記憶體崩潰,在這些情況下,需要考慮使用生成器運算式,
從語法上講,這兩個非常相似,它們之間的唯一區別是,您可以使用宣告串列推導[]和,使用來宣告生成器運算式(),就像這樣:
list_compr = [x**2 for x in range(10)] gen_expr = (x**2 for x in range(10)
關鍵是要對串列理解進行評估,在互動式shell中定義串列理解后,我們將獲得結果串列:
>>> [x**2 for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
相反,生成器運算式將回傳生成器物件:
>>> (x**2 for x in range(10)) <generator object <genexpr> at 0x0000023DD840F7C8>
生成器正常運行,需要使用next()方法,迭代生成器運算式或使用類似list(),set()或tuple()方法,
在上面的示例中,使用串列推導實際上更可取,當記憶體不是問題時,它們將優于生成器運算式,
當需要處理大量資料時,就會出現問題,因為串列推導會立即將所有輸出的資料存盤在記憶體中(就像我們在代碼中看到的那樣),
相反,生成器是一種概念,旨在一次生成一個(產量)結果,而不是將整個資料結構加載到記憶體中,這樣就可以處理龐大的資料集,而不會出現記憶體使用量激增的風險,
生成器的優點:
1.表情與像功能特別有用sum(),min()和max(),
2.生成器運算式可以輕松地鏈接(組合)在一起,從而創建一個資料管道,可以逐項處理大量資料,
缺點:不適用于需要多次使用這些值的情況,因為一旦生成器用盡,就無法訪??問其生成的值,
執行一個小型基準測驗,如何將生成器的運算式鏈接在一起,我們將要進行以下操作:
1)計算檔案中每行的長度,
2)然后從每行長度中提取平方根,
3)求平方根,
我使用.txt格式的“夏洛克·福爾摩斯歷險記”,你們可以選擇其他一些文本檔案,
讓我們首先使用串列推導:
import time execution = [] for i in range(100): start = time.time() filename = 'Sherlock Holmes.txt' lengths = [len(line) for line in open(filename)] roots = [x**0.5 for x in lengths] print(sum(roots)) end = time.time() execution.append(end-start) print(f'Avg execution time with list comprehensions: ' f'{sum(execution)/len(execution):.5f}')
使用生成器運算式,此代碼看起來幾乎相同:
import time execution = [] for i in range(100): start = time.time() filename = 'Sherlock Holmes.txt' lengths = (len(line) for line in open(filename)) roots = (x**0.5 for x in lengths) print(sum(roots)) end = time.time() execution.append(end-start) print(f'Avg execution time with generator expressions: ' f'{sum(execution)/len(execution):.5f}')
第二個塊將以不同的方式運行,Python不會在每一行上產生整個結果,而是從檔案中讀取一行,然后測量其長度,然后將其加到總和上,然后,解釋器將繼續進行下一行,依此類推,這正是將生成器運算式鏈接(組成)到資料管道中的意思,
因此,讓我們運行兩個版本:
Avg execution time with list comprehensions: 0.00486 Avg execution time with generator expressions: 0.00530
如您所見,在此資料集上,串列理解的運行速度更快,但是,如果我在包含超過1000萬行的檔案上運行相同的代碼,結果將有所不同(我只是將文本復制粘貼到Sherlock Holmes中多次):
Avg execution time with list comprehensions: 4.26855 Avg execution time with generator expressions: 3.79113
如您所見,在這種情況下,生成器運算式已被理解:
結論
綜上所述,生成器運算式在處理大型資料集時效率更高,并且可以幫助您的程式避免崩潰,而且,它們很容易鏈接在一起,從而創建了能夠一一生成結果值的資料管道,
同時,在較小的資料(較小的資料-取決于計算機)上,串列理解通常勝過生成器運算式,如果您需要多次訪問生成的資料,則串列理解會更有用,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/232932.html
標籤:其他
上一篇:2020年總結--還是輸給了自己
