从内存利用和CPU利用开始了解List和Tuple的优缺点

本文探讨了Python中List和Tuple的数据结构特性及其内存利用方式。List作为一种动态数组,在追加元素时会预留额外内存以提高效率;而Tuple作为静态数组,通过资源缓存和直接内存重用实现高效内存管理。

从内存利用和CPU利用开始了解List和Tuple的优缺点


定义 

List:动态数组,元素可变,可改变大小(append,resize)
Tuple:静态数组,不可变,数据一旦创建后不可改变


List的内存利用 
当创建N个元素的List时,Python的动态内存分配长N+1个元素的内存,第一个元素存储列表长度,和列表的元信息。 
当Append一个元素时,Python将创建一个足够大的列表,来容纳N个元素和将要被追加的元素。重新创建的列表长度大于N+1(虽然我们只触发一次append操作),实际上,为了未来的Append操作,M个元素长度(M>N+1)的内存将会被额外分配,然后,旧列表中的数据被copy到新列表中,旧列表销毁。 
额外内存的分配,只会发生在第一次Append操作时,当我们创建普通列表时,不会额外分配内存。 
这里的哲学是,一个Append操作很可能是很多Append操作的开始,通过额外分配内存来减少可能的内存分配和内存copy的次数。 
那么,对于一个具有N个元素的列表,当一次Append操作发生时,新列表要分配多少内存(额外M个元素,需多分配一个元素存储长度)呢?答案是: 

M = (N >> 3) + (N <9 ? 3 : 6) + 1


举例:
1)当一个具有100,000,000个元素的列表发生一次Append后,我们会实际分配一个长为112,500,007个元素长度的新列表。
2)当一个列表 l = [1, 2], l.append(3)后,M = (2 >> 3) + 3 + 1= 4, 新列表长度为4,l = [1,2,3, -]


Tuple的内存利用 
虽然Tuple不支持resize,但是我们可以粘贴两个元祖组成一个新的元组,这个操作类似于List的append,但是又不会额外的分配内存。但我们不能把它当成append,因为每次都会进行一个分配内存和内存copy操作。 
另一个Tuple的静态本质带来的好处是,resource caching。Python是garbage collected,当一个变量不用了,内存会被回收并交回给OS。但是,对于一个20个元素的Tuple,当它不再被用时,内存不会立即返还给OS,而是为了以后应用而暂缓保留,当一个新的Tuple被创建时,我们不会向OS重新申请分配内存,而是用现有reserved的free memory。 
也就是,Tuple的创建很简单并且避免频繁与OS申请内存,创建一个具有10个元素的Tuple比创建一个List要快不少,55ns VS 280 ns。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值