python:列表和元组,到底用哪个?

303 阅读3分钟
原文链接: mp.weixin.qq.com

   点击上方“代码视界”第一时间获取好内容

列表(list)和元组(tuple)是Python内置的两种数据结构,平时我们会经常使用到。 对于列表和元组的特点,下面几点学过Python的已经都很熟悉:
  • 列表和元组都是有序的,可以存储任意数据类型的集合。

  • 列表是动态,长度可变,可以随意增、删、改元素。

  • 元组是静态的,长度大小不可变,不可对元素进行增、删、改操作。

今天我们不讲列表和元组的定义和基本操作,我们来讲讲我们平常没注意的知识点

存储空间

列表和元组最重要的区别:列表是动态可变的,元组是静态不可变的。这样的差异,势必会影响两者的存储方式。 我们先看下面的例子:
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--

关注我们,升职加薪

干货|教程|交流|分享

我就知道你“在看”