元组和列表非常容易混淆,本节课有大量容易踩坑的细节,学习结束之后欢迎在评论区留下你的测试代码、疑问,大家一起交流学习!
一、课程前言
上一节课我们学习了列表 list,列表属于可变容器,可以随意新增、删除、修改数据。
本节课学习 元组(tuple),它属于有序、不可变序列容器,被称作密封版的列表。
日常开发适合存放固定不变的数据,例如坐标、日期、参数、常量;元组运行速度更快、内存占用更小,还可以作为字典的键。
二、基础概念详解
1. 元组核心定义
元组是存放多个数据的有序序列,元素引用地址固定、无法原地增删修改。
元组五大基础特性:
有序:拥有下标索引,支持正索引、负索引、切片
不可变(重点):不能直接修改、新增、删除内部元素
元素类型不限:可以存放整数、字符串、列表、嵌套元组
允许重复元素
可哈希:全部元素都是不可变类型时,可以当作字典 key、集合元素
通俗对比:
列表 = 可以随时打开、增减物品的购物袋
元组 = 封口密封袋,袋子内部物品位置不能更换
2. 四种创建元组方式(必考细节)
# 方式1:小括号创建,最标准写法t1 = (10, 20, 30, "python")# 方式2:省略括号,逗号本身就代表元组t2 = 5, 6, 7# 方式3:单元素元组,**必须带上逗号**,这是新手高频易错点t3 = (88,)print(type(t3))# 不带逗号只是普通整数,不是元组t4 = (88)print(type(t4))# 方式4:tuple() 构造器,把列表、字符串、range转为元组t5 = tuple([1,2,3])t6 = tuple("hello")t7 = tuple(range(1,5))
重点提醒:(数值)只是括号运算;(数值,)才是元组
3. 空元组
三、基础使用:索引、切片、查询、运算符
1. 索引取值
下标规则和列表完全一致:首位下标为0,末尾负索引‑1
t = ("苹果","香蕉","橙子","葡萄")print(t[0])print(t[-2])
2. 切片操作
切片会返回全新元组,原数据不会改动,遵循左闭右开
num = (10,20,30,40,50)print(num[1:3])print(num[:2])print(num[::-1]) # 元组反转,生成新元组
3. 查询内置方法
元组仅有两个内置查询方法,没有增删改方法
t = (11,22,33,22)# index:返回第一个匹配元素的下标print(t.index(22))# count:统计元素出现次数print(t.count(22))# in 判断元素是否存在print(33 in t)
4. 元组拼接、重复
a = (1,2)b = (3,4)print(a + b) # 拼接生成新元组print(a * 3) # 重复复制
四、核心特殊知识点 & 高频大坑
坑点1:元组不可变,仅代表元素地址不能修改
很多初学者误以为元组里面所有东西都不能改动。
元组存放的是元素的内存地址;如果元素本身是列表这类可变对象,列表内部可以正常修改
t = (10, [20, 30])# t[1] = [999] 报错,不能更换下标1的地址t[1].append(40)print(t)# 运行结果 (10, [20, 30, 40])
拆解理解:元组只是锁住袋子,袋子里面的购物袋(list)依旧可以往里面加东西。
坑点2:想要修改元组,只能先转为列表
元组本身无法修改,变通方案:tuple → list → 修改 → 转回tuple
t = (1,2,3)lst = list(t)lst.append(4)new_tuple = tuple(lst)print(new_tuple)
坑点3:嵌套元组
nest = (10, 20, (30,40))print(nest[2][0])
坑点4:元组拆包(解包,非常常用)
可以一次性把元组的值赋值给多个变量
# 基础拆包point = (12.5, 30.8)x, y = point# *星号拆包,批量接收多个元素data = (1,2,3,4,5)first, *mid, last = dataprint(mid) # mid为列表 [2,3,4]
拆包也是Python函数返回多个值的底层原理,函数返回多值本质就是返回元组
坑点5:元组可以作为字典的键,列表不行
只有可哈希、不可变的数据能够充当字典键;
当元组内部含有列表等可变对象,整体不可哈希,无法当作键
# 合法,全部元素不可变city = {(116,39):"北京"}# 报错,里面存放列表,不可哈希# bad = {(1, [2,3])}
坑点6:列表和元组核心区别对照表
对比项 | 列表 list | 元组 tuple |
符号 | 方括号 [] | 小括号 () |
可变性 | 可变,可以增删改 | 不可变,地址固定 |
内置方法 | append、pop、sort、extend等大量方法 | 只有 index()、count() |
内存速度 | 占用内存大、速度慢 | 占用内存更小、运行更快 |
哈希属性 | 不可哈希 | 元素全不可变则支持哈希 |
五、遍历循环元组
fruit = ("草莓","芒果","荔枝")# 普通for循环for i in fruit: print(i)# enumerate 获取下标和数值for index,val in enumerate(fruit): print(index,val)
六、课后练习题(共3题)
习题1(基础易错题)
请区分三者的数据类型:a=(5)、b=(5,),打印二者type查看结果。
习题2(经典陷阱题)
执行下面代码,写出最终打印结果,并说明原理:
test = (100, [200, 300])test[1].append(666)print(test)
习题3(拆包实操)
定义坐标元组 pos = (55,66),使用元组拆包把两个数值赋值给x、y变量,最后打印x和y。
元组最容易踩坑的就是单元素逗号、嵌套列表修改问题,如果你的代码运行报错或是有地方难以理解,可以在评论区留言,一起解决问题!