![Python基础及应用](https://wfqqreader-1252317822.image.myqcloud.com/cover/836/41309836/b_41309836.jpg)
4.2 Tuple(元组)
Tuple又叫元组,是一个线性结构,它的表达形式是这样的:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/72_01.jpg?sign=1739282197-YMGldxKx4aLiZFOhy1zEEVoaLQzWTjV7-0-7ebf704a29f4ff99b3a8ad905c21bc45)
即用一个圆括号括起来的一串对象就可以创建一个Tuple,之所以说它是一个线性结构是因为在元组中元素是有序的,比如我们可以这样去访问它的内容:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/72_02.jpg?sign=1739282197-CX4FjvqK5AUtsP6au2QxmW5RtdV0PmFF-0-3179b4b218411bc3c0b6117736672707)
这段代码会输出:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/72_03.jpg?sign=1739282197-lQ73SYnUiDJL5ygbSn6YZcnkWVKKnpJM-0-20f90aabdb1acf3b638ee287d3479057)
这里可以看到,我们通过“[]”运算符直接访问了Tuple的内容,这个运算符在上一章已经见过了,但是没有深入讲解。这里先详细学习切片操作符,因为它是一个非常常用的运算符,尤其在Tuple和List中应用广泛。
4.2.1 切片
1.背景
切片操作符和C/C++的下标运算符非常像,但是在C/C++中,“[]”只能用来取出指定下标的元素,所以它在C/C++中叫作下标运算符。
在Python中,这个功能被极大地扩展了——它不但能取一个元素,还能取一串元素,甚至还能隔着取、倒着取、反向取等。由于取一串元素的操作更像是在切片,所以我们称它为切片操作符。
灵活使用切片操作符,往往可以大大简化代码,这也是Python提供的便利之一。
2.取一个元素
如果有一个Tuple,并且我们想取出其中一个元素,可以使用具有一个参数的下标运算符:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/72_04.jpg?sign=1739282197-zqXMmHS2Qn3YMwXUKb208haDTDp6xSD8-0-a359ed4df524346397d4f81a6f3e1cd7)
绝大部分编程语言下标都是从0开始的,也就是说在Python中对于一个有n个元素的Tuple,自然数下标的范围是0~n-1。
所以这里会输出tuple1中下标为2的第3个元素:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_01.jpg?sign=1739282197-oWWqDm0k7mPG9S4RPW3VKtHNYxa4791L-0-8d1f910f0b03b2515d8d4061634b26c3)
这是切片操作符最简单的形式,它只接收一个参数就是元素的下标,也就是上面例子里的2。
特别地,Python支持负数下标表示从结尾倒着取元素,比如如果想取出最后一个元素:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_02.jpg?sign=1739282197-gjPsZK57JmDPe1W0qsXlTnFADRTZnoCo-0-e7aff5e74a6bcaaa2379dae60941ac04)
但是要注意的是负数下标是从-1开始的,所以对于一个含有n个元素的Tuple,它的负数下标范围为-1~-n,因此这里得到的是下标为4的最后一个元素,输出为:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_03.jpg?sign=1739282197-UtxzF8wvvtfZe1HtlikpEdqepYRIzFHX-0-99abebc5d70e9a9b028d87a19b1cfeda)
如果我们取了一个超出范围的元素:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_04.jpg?sign=1739282197-iuFAHgHdMZhmewspbdgPiNNCFPNYRjjH-0-902e053ad8822709dd757c82a52851c0)
那么Python解释器会抛出一个IndexError异常:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_05.jpg?sign=1739282197-j8xtZGN9jNmBtqkIgqcYJf53eEZ7VEbr-0-a7e5c27f7d386d9a3709181e86c8f28b)
这个异常的详细信息是下标超出了范围。如果遇到这种情况,需要检查一下代码是不是访问了不存在的下标。
3.取连续的元素
先看一个例子:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_06.jpg?sign=1739282197-OLRjyqrna5it1AZnpRZmXpNmJyuQgbRM-0-a93afe0d9975bdf0871c19ed3766bc0b)
这段代码会输出:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_07.jpg?sign=1739282197-J8QhhANnUCATPSKyN0IJUksBFOSVNWjy-0-4c81fef062a630d678f2fcd1a1ef5386)
我们会发现结果仍然是一个Tuple,由第1个到第4个元素之间的元素构成,其中包含第1个元素,但是不包含第4个元素。
这种切片操作接收两个参数,开始下标和结束下标,中间用分号隔开,也就是上面例子中的0和3,但是要注意的是元素下标区间是左闭右开的。如果对之前讲循环时候的range还有印象的话,可以发现它们的区间都是左闭右开的,这是Python中的一个规律。
特殊地,如果从第0个元素开始取,或者要一直取到最后一个,我们可以省略相应的参数,比如:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/73_08.jpg?sign=1739282197-YrDjIE1MSTS3YCXNrSIop0xIlNFgAqqU-0-0899ae99f87305c7e12a745070d80a78)
第一句表示从第1个元素取到第3个元素,第二句表示从第4个元素取到最后一个元素,所以输出为:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_01.jpg?sign=1739282197-hygYgBXLwGyzXVtSKKFAj1B7WqvLwWen-0-38e36aa4b63ae569118ae6bf48d44a85)
同样地,这里也可以使用负下标,比如:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_02.jpg?sign=1739282197-DVdxEDKLmzWIVhxEKHTNT83aLcTJBYZJ-0-303fc92f7a85e2a14b36dafeff53d474)
表示从第1个元素取到倒数第2个元素,所以输出为:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_03.jpg?sign=1739282197-x0qaJwlg0pVgAU3u80rGAdX1mKyzeeSg-0-8852f480b2bb35e5aca9ed9462a83d14)
4.以固定间隔取连续的元素
上述取连续元素的操作其实还可以进一步丰富,比如下面这个例子:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_04.jpg?sign=1739282197-IAsF8PHUONctUdvN5AMUHV79GqM8CvZx-0-357c21037ced3845458c630bf578431b)
这段代码会输出:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_05.jpg?sign=1739282197-4lAHwfMTdTQl1lYoAqn3mwRXv1KwuIH4-0-46fe5758d5929da252e25eb21ed39b9a)
这里表示的含义就是从第2个元素取到第5个元素,每2个取第1个元素。于是我们取出了第2个和第4个元素。这也是切片操作符的完整形式,即[开始:结束:间隔],例如上面的[1:4:2]。
特殊地,这个间隔可以是负数,表示反向间隔,例如:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_06.jpg?sign=1739282197-qYoABMe0zwjEJKygalVH4yTlh65FQZp4-0-f7d1208b1b2cb8a846b8732cf12b1dd1)
这句代码会输出:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_07.jpg?sign=1739282197-bEPvnKJDUTXA4FJFqe4Fi1f1J6JLYjbz-0-28786b82bcde29d693e77db1cdb3dfac)
可以看出就是翻转了整个Tuple。
4.2.2 修改
这里说的“修改”并不是原位的修改,因为Tuple的元素一旦指定就不可再修改,而是通过创建一个新的Tuple来实现修改,比如下面这个例子:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_08.jpg?sign=1739282197-CT42flytz7zYBAVJH2VqAlO19fjsKFPJ-0-90bbec63c4fdd439d394847e28702c75)
这段代码会输出:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/74_09.jpg?sign=1739282197-H5V6ImdQgeRcuwBc7NmSog7EKpV3YtgO-0-2dd5f81e45a6a69fa63d4ec1da5e811e)
可以看到我们通过创建tuple3和tuple4,“修改”了tuple1和tuple2。
同时要注意的是,之前在讲字符串的时候提到的加法和乘法对Tuple的操作也是类似的,效果分别是两个Tuple元素合并为一个新的Tuple和重复自身元素返回一个新的Tuple。
4.2.3 遍历
遍历有两种方法:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/75_01.jpg?sign=1739282197-MlP0nohZf1S3qWaPvVqw1kjzwZ6yvv5M-0-b044bfac7adc7e445e0cbe4b830202b4)
这段代码会输出:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/75_02.jpg?sign=1739282197-18pGhM1yEKnKzLSvDQaGjYVAV9tP7gEr-0-28c409d3141f545d892cc9c9cdc9efdd)
这里,在print函数中加了一个使结束符为空的参数,这个用法会在下一章函数中讲到,这里只要知道这样会使print不再自动换行就可以了。
我们可以通过一个for循环或者while循环直接顺序访问元组的内容。显然for循环不仅可读性高而且更加简单,在大多数情况下应该优先采用for循环。
另外值得一提的是,之所以Tuple可以这样用for遍历是因为Tuple包括后面马上要提到的List和Dict对象本身是可迭代的对象,这个概念之后会细讲,这里只要学会for循环的用法就可以了。
4.2.4 查找
在Tuple中查找元素可以用in,比如:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/75_03.jpg?sign=1739282197-7zfL5HYb0ra2mZdtShZmBfGlKm8uFXoL-0-f0b441fa00fa71e45739cdccaa197874)
这段代码会输出:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/75_04.jpg?sign=1739282197-wiCEfgLNFbcixY50pUsJuCYQtkw6jg7Y-0-22161742407df7a7a51bb8c19f20bab2)
in是一个使用广泛的用于判断包含的运算符,类似地还有not in。in的作用就是判断特定元素是否在某个对象中,如果包含就返回True,否则返回False。
4.2.5 内置函数
此外有一些内置函数可以作用于Tuple上,比如:
![](https://epubservercos.yuewen.com/82BE21/21511156608178806/epubprivate/OEBPS/Images/76_01.jpg?sign=1739282197-wr5G7O1R2JUp3KVFDMDwn1LW6RE19KYn-0-fa07968e0652743f39af84eba00c5bf8)
从上到下分别是求tuple1的长度、tuple1中最大的元素、tuple2中最小的元素。
这些函数对接下来即将讲到的List和Dict也有类似的作用。