将迭代器分配给Python切片

时间:2018-11-13 17:28:27

标签: python iterator 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返回一个迭代器,该迭代器选择两个要合并的迭代器中的最小元素。在切片分配发生之前会消耗掉这些迭代器吗?

2 个答案:

答案 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%+ 的存储空间。

  

请注意,切片量保持不变,但是内存   消费量显着增加。