簡體   English   中英

將迭代器分配給Python切片

[英]Assign iterators to a Python slice

在分配給Python中的切片之前是否消耗了迭代器? “分配前消耗”是指在切片分配發生之前,所有元素都同時在內存中創建(放入列表或元組)。 另一種方法是將迭代器中的元素逐一放入切片中,這樣就不會同時在內存中創建元素。

例如,讓我們考慮以下代碼:

from itertools import islice
from heapq import merge

c = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5] + list(range(10))
lo, mid, hi = 0, 10, 20
c[lo:hi] = merge(islice(iter(c), lo, mid), islice(iter(c), mid, hi))

merge返回一個迭代器,該迭代器選擇兩個要合並的迭代器中的最小元素。 在切片分配發生之前會消耗掉這些迭代器嗎?

這取決於切片分配到的序列的實現。 該序列直接接收迭代器,並且使用迭代器的詳細信息取決於序列。

對於列表,當前的CPython實現在對列表進行任何修改之前先消耗了迭代器

v_as_SF = PySequence_Fast(v, "can only assign an iterable");

PySequence_Fast將從尚未包含列表或元組的任何參數中構建列表。

還有自我分配處理,因為在將列表切片分配給自身時,將輸入轉換為列表還不夠安全:

/* Special case "a[i:j] = a" -- copy b first */
v = list_slice(b, 0, Py_SIZE(b));

我認為此列表行為均未記錄。

更新的答案:

是的,給定的可迭代對象在傳遞給slice()之前先消耗掉了

為了進行經驗證明,一個簡單的示例具有大約為的記憶。 消耗:

1.)包含10e6個數組元素的示例代碼。

from itertools import islice
from heapq import merge

c = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5] + list(range(int(10e6)))
lo, mid, hi = 0, 10, 20

c[lo:hi] = merge(islice(iter(c), lo, mid), islice(iter(c), mid, hi))

沒有明顯的時間和內存消耗。

2.)與數組的10e7元素相同的代碼。

c = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5] + list(range(int(10e7)))

表示相同配置的總內存消耗的30%

3.)與數組的10e8元素相同的代碼。

當然會達到100%+的內存需求。

請注意, 切片數量保持不變 ,但是內存消耗顯着增加。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM