列表和元组是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函数,可以直接调用,效率会更高。