一、列表与元组的相同点

1. 都是可以放置任意数据类型的有序集合

2. 列表和元组都支持切片操作

3. 列表和元组都可以随意嵌套

l = [[1, 2, 3], [4, 5]] # 列表的每一个元素也是一个列表

tup = ((1, 2, 3), (4, 5, 6)) # 元组的每一个元素也是一个元组

4. 两者也可以通过 list() 和 tuple() 函数相互转换

二、列表与元组的区别

1. 列表是动态的,长度大小不固定,可以随意地增加、删减或者改变元素; 而元组是静态的,长度大小固定,如果元组想要“改变”,就只能创建新的元组

tup = (1, 2, 3, 4)
new_tup = tup + (5, ) # 创建新的元组new_tup,并依次填充原元组的值
print(new_tup)  
>> (1, 2, 3, 4, 5)

l = [1, 2, 3, 4]
l.append(5) # 添加元素5到原列表的末尾
print(l)
>> [1, 2, 3, 4, 5]

2. 列表和元组存储方式的差异, 元组更加轻量级

示例1:

l = [1, 2, 3]
print(l.__sizeof__())
>> 64

tup = (1, 2, 3)
print(tup.__sizeof__())
>> 48

对比上面列表和元组,放置了相同的元素,而列表比元组多了16个字节。这是由于列表的动态性质,需要存储指针,来指向对应的元素(对于int型,8字节);还需要额外存储已经分配的长度大小(8字节),这样可以实时追踪列表的使用情况,当空间不足时,及时分配额外空间。

示例2:

l = []
print(l.__sizeof__())
>> 40     # 空列表的存储空间为40字节

l.append(1)
print(l.__sizeof__())
>> 72     # 加入了元素1之后,列表为其分配了可以存储4个元素的空间 (72 - 40)/8 = 4

l.append(2)
print(l.__sizeof__())
>> 72     # 由于之前分配了空间,所以加入元素2,列表空间不变

l.append(3)
print(l.__sizeof__())

>> 72     # 同上
l.append(4)
print(l.__sizeof__())

>> 72     # 同上
l.append(5)
print(l.__sizeof__())
>> 104    # 加入元素5之后,列表的空间不足,所以又额外分配了可以存储4个元素的空间

上示例子,大概描述了列表空间分配的过程。为了减小每次增加 / 删减操作时空间分配的开销,Python 每次分配空间时都会额外多分配一些,这样的机制(over-allocating)保证了其操作的高效性:增加 / 删除的时间复杂度均为 O(1)

而元组长度大小固定,元素不可变,所以存储空间固定

3. 元组比列表性能稍优

通过上面存储方式的差异,元组要比列表更加轻量级一些,所以总体上来说,元组的性能速度要略优于列表

另外,Python 会在后台,对静态数据做一些资源缓存(resource caching)。因为垃圾回收机制的存在,如果一些变量不被使用了,Python 就会回收它们所占用的内存,返还给操作系统,以便其他变量或其他应用使用

但是对于一些静态变量,比如元组,如果它不被使用并且占用空间不大时,Python 会暂时缓存这部分内存。下次我再创建同样大小的元组时,Python 就可以直接分配之前缓存的内存空间,能大大加快程序的运行速度

python元组和列表的区别 python列表和元组有何异同_python

三、列表和元组的使用

有一些场合你具体没有什么数据要改变。如果有最初不打算更改的数据,则应选择元组数据类型而不是列表。

如果数据会在应用程序运行时增长和缩小,则需要使用列表数据类型