一、元组的基础定义与特性
1. 什么是元组?
元组是有序、不可变、可包含任意数据类型(数字、字符串、列表、字典甚至另一个元组)的序列结构,用圆括号 () 包裹元素,元素之间用逗号分隔。
核心特性总结:
- 有序:元素有固定的索引位置,可通过索引访问
- 不可变:创建后无法修改、添加、删除元素(但可包含可变对象,如列表)
- 可哈希:可作为字典的键、集合的元素(列表不行)
- 支持重复元素:允许包含多个相同值的元素
2. 元组的创建
基本创建方式
# 方式1:带圆括号的标准创建
t1 = (1, 2, 3, "Python", True)
print(t1) # 输出:(1, 2, 3, 'Python', True)
# 方式2:省略圆括号(逗号分隔即可)
t2 = 10, 20, 30
print(t2) # 输出:(10, 20, 30)
# 方式3:单元素元组(必须加逗号,否则只是普通变量)
t3 = (5,) # 正确:元组
t4 = (5) # 错误:只是整数 5
print(type(t3)) # 输出:<class 'tuple'>
print(type(t4)) # 输出:<class 'int'>
# 方式4:空元组
t5 = ()
t6 = tuple() # 用 tuple() 构造函数
print(t5, t6) # 输出:() ()
# 方式5:从其他可迭代对象创建(列表、字符串等)
t7 = tuple([1, 2, 3]) # 从列表创建
t8 = tuple("hello") # 从字符串创建
print(t7) # 输出:(1, 2, 3)
print(t8) # 输出:('h', 'e', 'l', 'l', 'o')
二、元组的基本操作
1. 访问元素(和列表完全一致)
索引访问
元组的索引从 0 开始,支持正索引(从左到右)和负索引(从右到左,-1 表示最后一个元素):
t = (10, 20, 30, 40, 50)
print(t[0]) # 正索引:第一个元素,输出 10
print(t[-1]) # 负索引:最后一个元素,输出 50
print(t[2]) # 输出 30
切片访问
语法:元组[起始索引:结束索引:步长],切片返回新元组(因为原元组不可变):
t = (10, 20, 30, 40, 50)
print(t[1:4]) # 从索引1到3(左闭右开),输出 (20, 30, 40)
print(t[:3]) # 从开头到索引2,输出 (10, 20, 30)
print(t[2:]) # 从索引2到结尾,输出 (30, 40, 50)
print(t[::2]) # 步长2,输出 (10, 30, 50)
print(t[::-1]) # 步长-1,反转元组,输出 (50, 40, 30, 20, 10)
2. 元组的不可变性(重点)
元组创建后,直接修改元素会报错,这是和列表最核心的区别:
t = (1, 2, 3)
t[0] = 100 # 报错:TypeError: 'tuple' object does not support item assignment
特殊情况:元组包含可变对象
如果元组中的元素是可变类型(如列表),则该元素内部可以修改(元组本身的结构未变):
t = (1, [2, 3], 4)
t[1][0] = 200 # 修改列表元素,合法
print(t) # 输出:(1, [200, 3], 4)
3. 元组的常用操作(查、拼接、重复)
(1)查找元素
in/not in:判断元素是否存在index():返回元素第一次出现的索引(元素不存在则报错)count():统计元素出现的次数
t = (1, 2, 3, 2, 4, 2)
print(3 in t) # 输出 True
print(5 not in t) # 输出 True
print(t.index(2)) # 输出 1(第一个2的索引)
print(t.count(2)) # 输出 3(2出现3次)
(2)拼接与重复
通过 + 拼接两个元组(生成新元组),通过 * 重复元组元素(生成新元组):
t1 = (1, 2)
t2 = (3, 4)
t3 = t1 + t2 # 拼接,输出 (1, 2, 3, 4)
t4 = t1 * 3 # 重复,输出 (1, 2, 1, 2, 1, 2)
(3)长度、最大值、最小值
t = (10, 5, 8, 20)
print(len(t)) # 长度,输出 4
print(max(t)) # 最大值,输出 20
print(min(t)) # 最小值,输出 5
print(sum(t)) # 求和(仅数字元组),输出 43
4. 元组的“修改”(间接方式)
元组本身不可修改,但可通过拼接+重新赋值的方式间接“修改”(本质是创建新元组):
t = (1, 2, 3)
t = t[:2] + (4,) + t[2:] # 在索引2位置插入4
print(t) # 输出:(1, 2, 4, 3)
# 删除元组(只能删除整个元组,不能删除单个元素)
del t # 删除后访问t会报错
三、元组的高级用法
1. 元组解包(Tuple Unpacking)
这是元组最实用的特性之一,可将元组的元素快速赋值给多个变量:
基本解包
t = (10, 20, 30)
a, b, c = t # 解包:a=10, b=20, c=30
print(a, b, c) # 输出:10 20 30
扩展解包(*)
用 * 接收剩余元素(返回列表),适合元素数量不确定的场景:
t = (1, 2, 3, 4, 5)
a, *b, c = t # a=1, b=[2,3,4], c=5
print(a, b, c) # 输出:1 [2, 3, 4] 5
*a, b = t # a=[1,2,3,4], b=5
print(a, b) # 输出:[1, 2, 3, 4] 5
交换变量(经典用法)
无需临时变量,直接交换两个变量的值:
x = 10
y = 20
x, y = y, x # 本质是 (y, x) 元组解包
print(x, y) # 输出:20 10
2. 元组作为函数的参数/返回值
(1)可变参数(*args)
函数中 *args 接收的是元组,用于处理任意数量的位置参数:
def sum_args(*args):
print(type(args)) # 输出:<class 'tuple'>
return sum(args)
print(sum_args(1, 2, 3)) # 输出:6
(2)返回多个值
函数返回多个值时,本质是返回一个元组(可省略圆括号):
def get_info():
return "Python", 3.14, [1,2] # 等价于 return ("Python", 3.14, [1,2])
result = get_info()
print(result) # 输出:('Python', 3.14, [1, 2])
lang, num, lst = get_info() # 解包返回值
print(lang, num, lst) # 输出:Python 3.14 [1, 2]
3. 元组与列表的性能对比
元组的不可变性使其比列表更高效:
- 内存占用更小:元组创建后内存固定,列表需要预留扩展空间
- 访问速度更快:无需考虑修改,Python 对元组的优化更好
- 可哈希:可作为字典键、集合元素(列表不行)
# 示例:元组作为字典键
dict1 = {(1, 2): "坐标"}
print(dict1[(1, 2)]) # 输出:坐标
# 列表作为键会报错
# dict2 = {[1,2]: "坐标"} # TypeError: unhashable type: 'list'
四、元组的常用场景
- 存储不可变的数据:如配置项、坐标、固定的常量集合
- 函数返回多个值:天然支持解包,代码更简洁
- 作为字典的键:需要哈希able类型时(列表不行)
- 多变量赋值/交换:简化代码(如
a, b = b, a) - 保护数据:防止意外修改(比列表更安全)
五、元组与列表的核心区别
| 特性 | 元组 (Tuple) | 列表 (List) |
|---|---|---|
| 语法 | 圆括号 ()(可省略) |
方括号 [] |
| 可变性 | 不可变 | 可变 |
| 可哈希 | 可哈希(可作为字典键) | 不可哈希 |
| 内存占用 | 更小 | 更大(预留扩展空间) |
| 常用方法 | 仅查询类方法(index/count) | 增删改查全支持(append/pop等) |
总结
- 核心特性:元组是有序、不可变的序列,不可直接修改元素,但可包含可变对象(如列表),且可哈希(可作为字典键)。
- 核心用法:元组解包(多变量赋值、函数返回值)是其最实用的特性,比列表更高效、更安全。
- 使用场景:存储固定数据、函数返回多值、作为字典键、保护数据不被意外修改时优先使用元组;需要频繁增删改时用列表。
书签篮