元组是 Python 中另一个重要的序列结构,和列表类似,也是由一系列按特定顺序排序的元素组成。和列表不同的是,列表可以任意操作元素,是可变序列;而元组是不可变序列,即元组中的元素不可以单独修改。元组中也可以包涵不同的数据类型。
元组可以看做是不可变的列表。通常情况下,元组用于保存不可修改的内容。
从形式上看,元组的所有元素都放在一对小括号“()”中,相邻元素之间用逗号“,”分隔。但其实元组最重要的形式是逗号“,”,小括号“()”可不要,只要将各元素用逗号隔开,Python 就会将其视为元组,不过为了规范一般都会加上,举个例子:
>>>tuple1 = (1)
>>>type(tuple1)
<class 'int'>
>>>tuple1 = 1,2,3
>>>type(tuple1)
<class 'tuple'>
如果要定义只有一个元素的元组,必须要在元素后面加上逗号“,”,即>>>tuple1 = (1,)。
tuple元组修改方法
元组是不可变序列,元组中的元素不可以单独进行修改。但是,元组也不是完全不能修改,可通过以下几种方法修改元组:
1)重新赋值
2)拼接多个不同元组,添加新元素
3)元组切片,删除部分元素
4)del语句,删除整个元组
(注:在实际开发中, del() 语句并不常用,因为Python自带的垃圾回收机制会自动销毁不用的元组)
元组和列表最大的区别
元组和列表最大的区别就是,列表中的元素可以进行任意修改,就好比是用铅笔在纸上写的
字,写错了还可以擦除重写;而元组中的元素无法修改,除非将元组整体替换掉,就好比是用圆珠笔写的字,写了就擦不掉了,除非换一张纸。
需要注意的是,这样的差异势必会影响两者的存储方式,我们来直接看下面的例子:
>>> listdemo = []
>>> listdemo.__sizeof__()
40
>>> tupleDemo = ()
>>> tupleDemo.__sizeof__()
24
可以看到,对于列表和元组来说,虽然它们都是空的,但元组却比列表少占用 16 个字节,
这是为什么呢?
事实上,就是由于列表是动态的,它需要存储指针来指向对应的元素(占用 8 个字节)。另外,由于列表中元素可变,所以需要额外存储已经分配的长度大小(占用 8 个字节)。但是对于元组,情况就不同了,元组长度大小固定,且存储元素不可变,所以存储空间也是固定的。
既然列表这么强大,还要元组这种序列类型干什么?
通过对比列表和元组存储方式的差异,我们可以引申出这样的结论,即元组要比列表更加轻
量级,所以从总体上来说,元组的性能速度要由于列表。
另外,Python 会在后台,对静态数据做一些资源缓存。通常来说,因为垃圾回收机制的存在,如果一些变量不被使用了,Python 就会回收它们所占用的内存,返还给操作系统,以便其他变量或其他应用使用。
但是对于一些静态变量(比如元组),如果它不被使用并且占用空间不大时,Python 会暂时缓存这部分内存。这样的话,当下次再创建同样大小的元组时, Python 就可以不用再向操作系统发出请求去寻找内存,而是可以直接分配之前缓存的内存空间,这样就能大大加快程序的运行速度。
下面的例子,是计算初始化一个相同元素的列表和元组分别所需的时间。我们可以看到,元组的初始化速度要比列表快 5 倍。
C:\Users\mengma>python -m timeit 'x=(1,2,3,4,5,6)'
20000000 loops, best of 5: 9.97 nsec per loop
C:\Users\mengma>python -m timeit 'x=[1,2,3,4,5,6]'
5000000 loops, best of 5: 50.1 nsec per loop
当然,如果你想要增加、删减或者改变元素,那么列表显然更优。因为对于元组来说,必须得通过新建一个元组来完成。
总的来说,元组确实没有列表那么多功能,但是元组依旧是很重要的序列类型之一,元组的不可替代性体现在以下这些场景中:
1. 元组作为很多内置函数和序列类型方法的返回值存在,也就是说,在使用某些函数或者方法时,它的返回值会是元组类型,因此你必须对元组进行处理。
2. 元组比列表的访问和处理速度更快,因此,当需要对指定元素进行访问,且不涉及修改元素的操作时,建议使用元组。
3. 元组可以在映射(和集合的成员)中当做“键”使用,而列表不行。