元组(tuple)是 Python 中内置的不可变有序序列类型,用于存储一组固定、不可修改的数据。
元组与列表的区别,具有:
- 不可变性:元组一旦创建完成,不能修改、添加、删除其中的元素,这是它和列表最大的区别。
- 有序性元素按照定义顺序存储,支持通过下标索引访问。
- 可重复、可任意嵌套支持存储重复元素,可嵌套数字、字符串、列表、元组等任意数据类型。
- 使用小括号
()表示这是元组最直观的标识。
适用场景:
- 存储不希望被修改的固定数据(如配置项、坐标、常量)
- 函数多返回值传递(底层默认用元组)
- 数据解包、多变量赋值
- 作为字典的键(列表不可以)
元组就像一个密封好的固定容器,放进去什么就是什么,不能再改动;而列表是打开的盒子,可以随时增删改内容。
| 特性 | 元组 (tuple) | 列表 (list) |
|---|---|---|
| 符号 | () | [] |
| 可变性 | 不可变(只读) | 可变(可增删改) |
| 内置方法 | 少(仅查询) | 多(增删改查) |
| 适用场景 | 固定数据、保护数据 | 频繁变动的数据 |
一、常用基础操作
1. 索引与切片
语法:元组[start:stop:step],规则和列表完全一致
- 索引:通过下标获取单个元素,支持正负索引
- 切片:截取部分元素,左闭右开,步长可自定义
- 反转:利用反向切片
[::-1]实现元组整体 / 局部反转
2. 拼接与重复
- 拼接:使用
+合并两个元组,生成新元组 - 重复:使用
*复制元组内容,生成新元组
3. 成员判断
通过in/not in判断元素是否存在于元组中,返回布尔值True/False。
4. 遍历循环
使用for循环直接遍历元组,依次取出每个元素。
二、元组内置方法(仅 2 个)
元组不可变,方法远少于列表,仅提供查询类方法:
count(元素):统计指定元素在元组中出现的次数index(元素):查找指定元素第一次出现的索引,元素不存在则直接报错
三、元组解包(高频实用技巧)
将元组元素一次性赋值给多个变量,日常开发、数据接收场景使用极多。
- 标准解包:变量数量 = 元组元素数量
- 占位符
_:接收不需要的元素,作为匿名占位 - 星号
*多元素打包:*变量可接收多个连续元素,并自动转为列表
四、元组嵌套
元组内部可嵌套列表、其他元组等数据类型:
- 元组本身不可变,无法修改元组顶层元素
- 若元组内嵌套列表(可变类型),列表内部元素可以正常修改
五、内存地址特性
元组属于不可变对象,Python 会对内容相同的小型元组做内存缓存优化: 内容一致的元组,大概率指向同一个内存地址(id()结果相同);元组创建后自身内存地址永远不会改变。
#元组不同于列表,是不可变的,元组使用小括号(),列表使用中括号[]。 #元组的基本操作和列表类似,可以进行索引、切片、连接、重复等操作,但不能修改元组中的元素。 #创建一个元组 tuple_1 = (1,2,3,4,5) print(tuple_1) #输出:(1, 2, 3, 4, 5) #如果元组中只有一个元素 tuple_only_one = (1,)#格式应该是数字后添加,如果不添加则不是 print(type(tuple_only_one)) #不添加逗号 tuple_2 = (1) print(type(tuple_2))#输出:<class 'int'>,说明不是元组 #不添加逗号的时候,括号(2)表示的就是2,只是添加了括号运算优先级 print(type("abc"))#输出:<class 'str'> #元组的索引和切片 tuple_3 = (1, 2, 3, 4, 5) print(tuple_3[0]) #输出:1 print(tuple_3[1:4]) #输出:(2, 3, 4) print(tuple_3[-1]) #输出:5 print(tuple_3[::2])#输出:(1, 3, 5) #[start:stop:step],其中start表示切片的起始位置,默认为0;stop表示切片的结束位置,不包含stop位置的元素;step表示切片的步长,默认为1. #如果对全部的数据进行操作,则start,stop可以省略,直接为[::step] print(tuple_3[:])#打印全部元素 print(tuple_3[::])#打印全部元素,step省略表示默认为1,start和stop省略表示默认为0和len(tuple_3),即从头到尾进行切片操作。 #元组进行反转 tuple_3_reversed = tuple_3[::-1]#-1表示反向切片,即从最后一个元素开始,步长为-1,依次取出元素,直到第一个元素为止。 print(tuple_3_reversed) #输出:(5, 4, 3, 2, 1) tuple_3_a = tuple_3[1:4][::-1]#想要对部分片段继续进行反转,先对部分片段进行切片操作,再对切片结果进行反转。 print(tuple_3_a) #元组常用的内置方法 .conut()和.index() 分别表示元素出现的次数和第一个元素出现的位置 tuple_3 = (1, 2, 3, 4, 5,1,1,1,2) print(tuple_3.count(2)) #输出:2,count方法用于统计元组中某个元素出现的次数 print(tuple_3.index(3)) #输出:2,index方法用于查找元素在元组中的索引位置,找不到直接报错,如果有多个相同的元素,则返回第一个元素的索引位置。 print(tuple_3.count(1)) #输出:4,统计元素1在元组中出现的次数 print(tuple_3.index(2)) #输出:1,查找元素2在元组中的索引位置,返回第一个元素2的索引位置。 # print(tuple_3.index(7)) #输出:ValueError: tuple.index(x): x not found,查找元素7在元组中的索引位置,找不到直接报错。 #元组的连接和重复 tuple_4 = (1, 2, 3) tuple_5 = (4, 5, 6) tuple_6 = tuple_4 + tuple_5 #连接 print(tuple_6) #输出:(1, 2, 3, 4, 5, 6) #***************************************** tuple_7 = tuple_4 * 3 #重复 print(tuple_7) #输出:(1, 2, 3, 1, 2, 3,1,2,3) #创建空元组 tuple_8 = () tuple_9 = tuple() print(f"type(tuple_8):{type(tuple_8)}")#type(tuple_8):<class 'tuple'> print(f"type(tuple_9):{type(tuple_9)}")#type(tuple_9):<class 'tuple'> #将列表转为元组 list_1 = [1,2,3] list_convert_tuple = tuple(list_1) print(list_convert_tuple) #输出:(1, 2, 3) print(type(list_convert_tuple)) #输出:<class 'tuple'> #成员判断 in / not in tuple_10 = (1,4,6,7,8,9) print(4 in tuple_10) #输出:True,判断元素4是否在元组tuple_10中 print(5 in tuple_10) #输出:False,判断元素5是否在元组tuple_10中 print(5 not in tuple_10) #输出:True,判断元素5是否不在元组tuple_10中 print(100 not in tuple_10) #输出:True,判断元素100是否不在元组tuple_10中 #遍历循环 tuple_11 = (1,2,3,4,5) for i in tuple_11: print(i) #输出:1 2 3 4 5,依次输出元组tuple_11中的每个元素prin #其中的print(i)语句在循环体内,每次循环都会执行一次,输出当前元素i的值。循环结束后,所有元素都被输出完毕。 #print(tuple_11[0],tuple_11[1],tuple_11[2],tuple_11[3],tuple_11[4])#输出:1 2 3 4 5,依次输出元组tuple_11中的每个元素 #解包***重要,常用*** #解包:将元组中的元素依次赋值给多个变量,变量的数量必须与元组中的元素数量相同。 tuple_12 = (1, 2, 3) ta,tb,tc = tuple_12 print(f"ta:{ta},tb:{tb},tc:{tc}")#ta:1,tb:2,tc:3,依次将元组tuple_12中的元素赋值给变量ta、tb、tc,并输出变量的值。 #如果只想要去除元组中的某个元素,可以使用占位符_,表示不需要的元素。 tuple_13 = (1, 2, 3, 4) _,tb,tc,_ = tuple_13 print(f"tb:{tb},tc:{tc}")#tb:2,tc:3 print(f"_:{_}")#_:4,占位符_表示不需要的元素4,但在解包过程中仍然会被赋值给变量_,所以输出的结果是4._第一次是1,第二次是4,最后一次是4. #如果元组中元素多,只想去第一个和最后一个元素,可以使用*运算符,将中间的元素打包成一个列表。 tuple_14 = (1, 2, 3, 4, 5) t1,t2,*t3,t5 = tuple_14 print(f"t1:{t1},t2:{t2},t3:{t3},t5:{t5}")#t1:1,t2:2,t3:[3, 4],t5:5,使用*运算符将元组tuple_14中的中间元素3和4打包成一个列表t3,并输出变量的值。t1和t2分别获取第一个和第二个元素,t5获取最后一个元素。 #元组的嵌套 元组中可以嵌套列表,也可以嵌套其他元组。 tuple_15 = (1,2,[3,4],(5,6),7) print(type(tuple_15))#输出:<class 'tuple'>,说明tuple_15是一个元组 print(type(tuple_15[2]))#输出:<class 'list'>,说明tuple_15中的第三个元素是一个列表 #那是否可以对元组中的列表进行修改呢? # 答案是可以的,因为元组本身是不可变的,但元组中的元素如果是可变类型(如列表),则可以修改该元素。 tuple_15[2][0] = 30 print(tuple_15) #输出:(1, 2, [30, 4], (5, 6), 7),说明虽然元组tuple_15本身不可变,但其中的列表元素可以被修改。 #元组本身不能修改, # tuple_15[0] = 10 #输出:TypeError: 'tuple' object does not support item assignment,说明元组tuple_15的第一个元素不能被修改,因为元组是不可变的。 #元组的内存地址 tuple_16 = (1, 2, 3) print(id(tuple_16)) tuple_17 = (1, 2, 3) print(id(tuple_17)) #tuple_16和tuple_17的内存 地址可能相同,也可能不同,这取决于Python的内存管理机制。在某些情况下,Python会对小整数进行缓存,因此tuple_16和tuple_17可能指向同一个内存地址。但在其他情况下,它们可能指向不同的内存地址。总之,元组是不可变的,因此它们的内存地址不会改变。