[英]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.