[英]Iterators in Python 3
在Python 3中,許多返回列表的函數(現在是類)現在返回iterables,最常見的例子是range
。 在這種情況下,范圍在Python 3中是可迭代的,以提高性能和內存效率(因為您不必再構建列表)。
其他“新” iterables是map
, enumerate
, zip
和字典操作的輸出dict.keys()
dict.values()
和dict.items()
(可能還有更多,但我不知道)。
其中一些( enumerate
和map
)通過將它們轉換為迭代可能變得更有效。 在Python 2.7中,其他人只是創建了已經在內存中的對象列表,因此它們可以提高內存效率。
為什么然后將它們變成可以在每次要對它們進行排序時必須轉換為列表的迭代,等等?
幾個原因:
字典操作現在返回字典視圖對象 ; 這些也可以作為集合,為您提供更豐富的對象,以便在您的代碼中使用。 在Python 2中,你必須使用dict.view*()
方法來做同樣的事情。
Python 2中的字典操作產生了一個新的列表對象; 即使索引引用現有對象,列表對象也會占用內存。 這里還有另一個副作用; 列表索引會增加所有這些字典內容的引用計數,這也會影響性能(並且可能會刷新CPU緩存)。
zip()
和map()
總是可以處理任何迭代,包括生成器,但是在應用時會將所有內容都拉到一個大的列表中。 通過在Python 3中將它們轉換為生成器,它們不再自動消耗這樣的迭代。
請注意,Python 2中的enumerate()
從未返回過列表,它總是返回一個迭代器。
只需在這些對象上應用list()
就可以始終獲得舊的Python 2行為。 如果你需要排序的項目,你可以在iterable上調用sorted()
。 但是你現在可以選擇而不是強制列表對象。
對於Python中的大多數用例,您從未真正需要一個完整的列表。 您通常會迭代這些結果。 對它們進行排序不是最常見的用例,索引它們也不是。 因此,對於大多數用例而言,更改是一種勝利,為程序員提供了僅使用標准函數和類型生成更高效代碼的工具。
如果你想對它們進行排序,那么迭代需要轉換成一個列表( sorted
將為你處理)...但是你要多久經常對一個enumerate
對象進行排序,與你再次迭代的頻率相比超過它? 那么對dict的items
進行排序,與僅僅迭代它們相比呢?
如果您的API生成了一個惰性迭代器或其他惰性迭代器,您可以將其轉換為一個列表,與跳過迭代器並直接生成列表所花費的工作量大致相同。 另一方面,如果您的API生成一個列表,則無法避免一次性將所有項目保留在內存中。 迭代器更靈活。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.