在python中,array.array是一个可变结构。
但是,我不确定插入操作在array.array结构中是如何工作的。
由于array.array使用连续内存,如果新元素不能以连续方式放置,它是否会创建一个新的内存块并复制数组的所有元素?它是否为插入操作预留了额外的未使用空间?
Listing[Python3.Docs]:数组-数值的高效数组,以防万一。
任何一个体面的容器都可以将数据保存在一个连续的内存区域中,分配的内存超过了保存当前元素数量所需的内存
如果在插入(附加是一种特殊情况(一个元素时没有额外元素的空间,会发生什么:
- 分配内存区域(当前大小+1(元素大小((
- 将数据复制到新区域
- 免费旧区
- 无论如何都要执行其他小操作(如大小(计数器(更新…(
如图所示,在追加(这是添加元素的最常见操作(时,会有大量工作需要时间和资源(CPU电源、内存(。
现代容器有一个不断增长的策略算法:每次需要重新分配内存区域(容器已满(时,都会在现有大小上添加一个N元素来计算新大小,而且更多:每次重新分配时,N都会变大。这是为了最大限度地减少(昂贵的(内存操作
当然,在间隔的另一端,可能会为一个容器分配大量内存(例如500 MiB(,但这是不可行的,因为大量内存将"保留"在那里,以备拥有容器可能需要。
毕竟,这只是一个折衷的问题。
您可以检查[CPPReference]:std::vector作为示例(大小和容量方法(。
回到我们的问题:array.array
确实是一个会分配未使用空间的现代容器。来自[GitHub]:python/cpython-(master(cpython/Modules/arraymodule.c:
于插入算法本身,请检查ins1函数:/* This over-allocates proportional to the array size, making room * for additional growth. The over-allocation is mild, but is * enough to give linear-time amortized behavior over a long * sequence of appends() in the presence of a poorly-performing * system realloc(). * The growth pattern is: 0, 4, 8, 16, 25, 34, 46, 56, 67, 79, ... * Note, the pattern starts out the same as for lists but then * grows at a smaller rate so that larger arrays only overallocate * by about 1/16th -- this is done because arrays are presumed to be more * memory critical. */
- 检查(并更新(大小,如果需要,会增加内存
- 插入位置之后的元素将向一端("右侧"(移动一个位置
- 新元素被放置在插入位置
顺便说一句,其他Python容器都使用这种技术,请检查[SO]:为什么列表会询问__len__?(@CristiFati的回答(了解更多细节。