功能差异
列表是动态的,可拓展的。
元组是静态的,不可拓展的。对元组的增删操作只能通过新建一个元组进行操作。
底层实现的差异
- 列表是一个大小可变的连续数组,同时有一个指针列表,存储的指针指向列表中的每个元素。
- 列表的大小是动态变化的,类似于C语言实现的动态数组,支持动态扩展,当数组满时,增加一个元素,此时一次申请4个元素的空间。
l = []
l.__sizeof__() // 空列表的存储空间为40字节
40
l.append(1)
l.__sizeof__()
72 // 加入了元素1之后,列表为其分配了可以存储4个元素的空间 (72 - 40)/8 = 4
l.append(2)
l.__sizeof__()
72 // 由于之前分配了空间,所以加入元素2,列表空间不变
l.append(3)
l.__sizeof__()
72 // 同上
l.append(4)
l.__sizeof__()
72 // 同上
l.append(5)
l.__sizeof__()
104 // 加入元素5之后,列表的空间不足,所以又额外分配了可以存储4个元素的空间
- 元组是静态的,元组是一个大小固定的数组。
t = tuple()
t.__sizeof__()
24
空的列表比空的元组空间大16字节,是因为,列表需要指针指向元素(8字节),记录已分配的空间大小(8字节)。
(满的列表也是比同样的元组多16字节。)
性能差异
- 列表的性能稍微差于元组。
- 初始化操作,列表的初始化时间大约为元组的5倍。
- 查找操作几乎相同
- 删除、增加只能用列表,因为元组只能生成一个新的元组。
python3 -m timeit 'x=(1,2,3,4,5,6)'
20000000 loops, best of 5: 9.97 nsec per loop
python3 -m timeit 'x=[1,2,3,4,5,6]'
5000000 loops, best of 5: 50.1 nsec per loop
- Python 会在后台,对静态数据做一些资源缓存(resource caching)。通常来说,因为垃圾回收机制的存在,如果一些变量不被使用了,Python 就会回收它们所占用的内存,返还给操作系统,以便其他变量或其他应用使用。
但是对于一些静态变量,比如元组,如果它不被使用并且占用空间不大时,Python 会暂时缓存这部分内存。这样,下次我们再创建同样大小的元组时,Python 就可以不用再向操作系统发出请求,去寻找内存,而是可以直接分配之前缓存的内存空间,这样就能大大加快程序的运行速度。
使用场景差异
- 数据量不变的,使用元组。
- 数据会动态变化的,使用列表。
a=[] #性能更优
a=list()
因为list()涉及到函数调用,会创建stack,并且进行一系列参数检查的操作。
而 [] 是一个内置的C函数,可以被直接调用。
网友评论