在使用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返回一个迭代器,该迭代器选择两个要合并的迭代器中的最小元素。在切片分配发生之前会消耗掉这些迭代器吗?
答案 0 :(得分:2)
这取决于切片分配到的序列的实现。该序列直接接收迭代器,使用迭代器的详细信息取决于序列。
对于列表,对列表进行任何修改之前的当前CPython实现consumes the iterator up front:
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));
我认为没有任何有关此列表行为的记录。
答案 1 :(得分:-1)
更新后的答案:
是的,给定的 iterables 会在传递给slice()之前消耗:
为进行经验证明,一个简单的示例使用了大约10的内存。消费:
1。)示例代码,其中包含 10e6 个数组元素。
cannot read property 0 of undefined
没有明显的时间和内存消耗。
2。)与数组 10e7 元素相同的代码。
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))
相同配置的仅占内存总消耗的 30%。
3。)与 10e8 数组元素相同的代码。
当然需要 100%+ 的存储空间。
请注意,切片量保持不变,但是内存 消费量显着增加。