点击上方“代码视界”第一时间获取好内容
-
列表和元组都是有序的,可以存储任意数据类型的集合。
-
列表是动态,长度可变,可以随意增、删、改元素。
-
元组是静态的,长度大小不可变,不可对元素进行增、删、改操作。
存储空间
list = [1, 2, 3]list.__sizeof__()64tup = (1, 2, 3)tup.__sizeof__()48
从上面的例子中,我们在列表和元组中放置了相同的元素,但是列表的存储空间却比元组多16字节。
由于列表是动态的,所以它需要存储指针,来指向对应的元素(上述例子中,对于 int 型,8 字节)。另外,由于列表可变,所以需要额外存储已经分配的长度大小(8 字节),这样才可以实时追踪列表空间的使用情况,当空间不足时,及时分配额外空间。
list = []list.__sizeof__() // 空列表的存储空间为 40 字节40list.append(1)list.__sizeof__() 72 // 加入了元素 1 之后,列表为其分配了可以存储 4 个元素的空间 (72 - 40)/8 = 4list.append(2) list.__sizeof__()72 // 由于之前分配了空间,所以加入元素 2,列表空间不变list.append(3)list.__sizeof__() 72 // 同上list.append(4)list.__sizeof__() 72 // 同上list.append(5)list.__sizeof__() 104 // 加入元素 5 之后,列表的空间不足,所以又额外分配了可以存储 4 个元素的空间
上面的例子,大概描述了列表空间分配的过程。我们可以看到,为了减小每次增加 / 删减操作时空间分配的开销,Python 每次分配空间时都会额外多分配一些,这样的机制(over-allocating)保证了其操作的高效性:增加 / 删除的时间复杂度均为 O(1)。
但是对于元组,情况就不同了。元组长度大小固定,元素不可变,所以存储空间固定。
性能
python -m timeit 'x=[1,2,3,4,5,6]'10000000 loops, best of 3: 0.0812 usec per looppython -m timeit 'x=(1,2,3,4,5,6)'10000000 loops, best of 3: 0.0185 usec per loop
我们可以看到,元组的初始化速度,要比列表快 5 倍。
但如果是索引操作的话,两者的速度差别非常小,几乎可以忽略不计。
python -m timeit -s 'x=[1,2,3,4,5,6]' 'y=x[3]'10000000 loops, best of 3: 0.0338 usec per looppython -m timeit -s 'x=(1,2,3,4,5,6)' 'y=x[3]'10000000 loops, best of 3: 0.0357 usec per loop
总结
-
列表和元组都是有序的,可以存储任意数据类型的集合。
-
列表是动态的,长度可变,可以随意增加、删减、改变元素。
-
元组是静态的,长度大小固定,不可对元素进行增加、删减、改变操作。
-
列表的存储空间略大于元组,性能略逊于元组。元组相对列表更轻量级。
--End--
关注我们,升职加薪
干货|教程|交流|分享
我就知道你“在看”