一.列表和元组的使用

列表和元组是Python最常用的基本数据结构,我们来比较一下两者的特点

列表和元组的特点

1.列表和元组是一个可以放置任何数据类型的有序集合

>>> list = [1,2.2,'abc']
>>> list
[1, 2.2, 'abc']
>>> tuple = (1,2.2,'abc')
>>> tuple
(1, 2.2, 'abc')

可以看出来,在同一个列表或元组里是可以有不同类型的数据的。(在上面的例子中就包含了一个int,一个float和一个str。)

2.Python里的列表和元组都支持负数索引、切片操作和随意的嵌套

3.Python里的列表和元组可以通过list()和tuple()随意转换

列表和元组的区别

列表是动态的,长度和大小不固定,可以随时追加、删减和修改元素

>>> list = [1,2.2,'abc']
>>> list.append('aaa')
>>> list[0]=123
>>> list
[123, 2.2, 'abc', 'aaa']

元组是静态的,长度和大小是固定的,无法增加、删减和修改。

>>> tuple = (1,2.2,'abc')
>>> tuple[0]=123
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

在对元组修改时,就会有错误抛出。可是如果想要修改元组,那该怎么办呢?就要重新开一块内存,创建一个新的元组。就像要把一个元组加一个元素,就要这么办

>>> tuple = (1,2,3,4,)
>>> tuple_new = tuple+(5,)
>>> tuple_new
(1, 2, 3, 4, 5)

创建了一个新的元组,两个元组和在一起。

列表和元组存储方式的差异

我们先创建两个一样内容的列表和元组,再看一看他们占用的存储空间

>>> list = [1,2,3]
>>> list.__sizeof__()    #显示存储空间
64
>>> tuple = (1,2,3)
>>> tuple.__sizeof__()
48

可以看出来列表要比元组多出来16个字节,但是他们的内容是相同的。为什么呢?

因为列表是动态的,他需要存储指针来指向对应的元素(上面的例子中由于数据都是int型,占用8个字节)。另外,由于列表可变,所以需要额外存储已经分配的长度大小(8字节),当控件不足时,会会及时分配额外空间。我们可以试一下

>>> list = []
>>> list.__sizeof__() #空列表,存储空间为40字节
40
>>> list.append(1)
>>> list.__sizeof__() #加入1个元素,列表围棋分配了可以存储4个元素的空间(72-40)/8=4
72
>>> list.append(2)
>>> list.__sizeof__() #同上
72
>>> list.append(3)
>>> list.__sizeof__() #同上
72
>>> list.append(4)
>>> list.__sizeof__() #同上
72
>>> list.append(5) 
>>> list.__sizeof__() #加入了第5个元素,列表的空间不足,有额外分配了可以存储4个元素的空间
104

   空的列表所占用的内存是40字节,在添加一个元素后直接预留了4个元素的空间(4*8=32字节)。再添加4个元素预留的32个字节全部占用,再一次添加时会再一次预留32个字节。这就是列表空间分配的过程。为了减少每次增加、删减操作时空间分配的开销,Python每次分配空间的时候都会额外的多分配一些。这样的机制(over-allocationg)保证了操作的高效性:增加/删减的事件复杂度为O(1)。

  而对元组来说,由于其长度大小固定,元素也不可变,所以每次分配的空间是不会变的。

列表和元组的性能差异

  通过上面一节列表和元组在存储方式上的差异总结一下:元组是比列表更轻量级的数据结构,所以总体上来说,元组的性能速度要略优于列表。

  此外,Python在后台会对静态数据做一些资源缓存(resource caching)。就是说由于垃圾回收机制的存在,有些变量不被使用了,Python就会回收他们所占用的资源交还给操作系统,以便于其他的变量或应用使用。而对于这些静态变量,由于他不被使用并且占用的空间不大时,Python会暂时缓存这部分内存,这样下次我们再创建同样大小的变量时Python就不需要想操作系统发出请求去寻找内存,而是从之前缓存的内存空间里寻找。这样就能大大加快程序的运行速度。

总结

·列表是动态的,长度可变,存储控件略大于元组,性能略逊于元组。

·元组是静态的,长度大小固定。相对于列表更轻量级,性能稍优,在传递参数的时候可以考虑使用元组。

想一想

创建一个空的列表可用下面两种方式

#option A
empty_list = list()
#option_B
empty_list = []

哪种效率高呢?

对了,是第二种。因为list()是调用了一个函数,Python的function call会创建stack并进行一系列参数检查操作,而[]是一个内置的C函数,可以直接调用,效率会更高。

猜你喜欢

转载自www.cnblogs.com/yinsedeyinse/p/10915056.html