1. 什么是元组?
元组(tuple)是 Python 中一种不可变(immutable)的有序序列类型。它用圆括号 () 定义,元素之间用逗号分隔。元组一旦创建,其内容就不能被修改(增、删、改),这使得它在存储不希望被意外更改的数据时非常有用。
元组与列表(list)的主要区别:
- 可变性:列表可变(mutable),元组不可变(immutable)。
- 语法 :列表用方括号
[],元组用圆括号()(括号有时可省略)。 - 性能:元组由于不可变性,通常比列表占用内存更少,创建和访问速度也略快。
- 用途:列表用于存储可能变化的数据集合;元组常用于存储固定不变的数据,如函数返回多个值、字典的键、配置项等。
2. 元组的创建与基本操作
2.1 创建元组
python
# 1. 使用圆括号(最常见)
tuple1 = (1, 2, 3, 4, 5)
print(tuple1) # (1, 2, 3, 4, 5)
# 2. 括号可省略(仅当元组非空且不是函数参数时)
tuple2 = 1, 2, 3
print(tuple2) # (1, 2, 3)
# 3. 创建单个元素的元组(必须加逗号)
single_tuple = (42,) # 正确
not_a_tuple = (42) # 错误,这只是一个整数 42
print(type(single_tuple)) # <class 'tuple'>
print(type(not_a_tuple)) # <class 'int'>
# 4. 使用 tuple() 构造函数
tuple3 = tuple([1, 2, 3]) # 从列表转换
tuple4 = tuple("hello") # 从字符串转换,得到 ('h', 'e', 'l', 'l', 'o')
print(tuple3, tuple4)
2.2 访问元组元素
元组支持索引和切片,语法与列表完全相同。
python
my_tuple = ('a', 'b', 'c', 'd', 'e')
# 正向索引(从0开始)
print(my_tuple[0]) # 'a'
print(my_tuple[2]) # 'c'
# 负向索引(从-1开始)
print(my_tuple[-1]) # 'e'
print(my_tuple[-3]) # 'c'
# 切片 [start:end:step]
print(my_tuple[1:4]) # ('b', 'c', 'd')
print(my_tuple[:3]) # ('a', 'b', 'c')
print(my_tuple[::2]) # ('a', 'c', 'e')
print(my_tuple[::-1]) # ('e', 'd', 'c', 'b', 'a'),反转元组
2.3 元组的不可变性
尝试修改元组元素会引发 TypeError。
python
immutable_tuple = (10, 20, 30)
# immutable_tuple[0] = 100 # TypeError: 'tuple' object does not support item assignment
但请注意,如果元组中包含可变对象(如列表),则该可变对象本身的内容可以修改。
python
mixed_tuple = (1, 2, [3, 4])
print(mixed_tuple) # (1, 2, [3, 4])
mixed_tuple[2].append(5) # 修改元组中列表的元素是允许的
print(mixed_tuple) # (1, 2, [3, 4, 5])
3. 元组的遍历
遍历元组与遍历列表方法一致,常用以下几种方式。
3.1 使用 for 循环
python
fruits = ('apple', 'banana', 'cherry')
# 直接遍历元素
for fruit in fruits:
print(fruit)
# 输出:
# apple
# banana
# cherry
# 同时获取索引和元素(使用 enumerate)
for index, fruit in enumerate(fruits):
print(f"Index {index}: {fruit}")
# 输出:
# Index 0: apple
# Index 1: banana
# Index 2: cherry
3.2 使用 while 循环
python
numbers = (10, 20, 30, 40, 50)
i = 0
while i < len(numbers):
print(numbers[i])
i += 1
3.3 使用列表推导式(生成的是列表)
如果需要基于元组元素生成新列表,可以使用列表推导式。
python
tuple_of_nums = (1, 2, 3, 4, 5)
squared_list = [x**2 for x in tuple_of_nums]
print(squared_list) # [1, 4, 9, 16, 25]
3.4 解包(Unpacking)
元组解包是 Python 中非常实用的特性,可以一次性将元组元素赋值给多个变量。
python
# 基本解包
point = (3, 5)
x, y = point
print(f"x={x}, y={y}") # x=3, y=5
# 交换两个变量的值(无需临时变量)
a, b = 10, 20
a, b = b, a # 本质上是元组打包和解包
print(f"a={a}, b={b}") # a=20, b=10
# 使用 * 收集多余元素
first, *middle, last = (1, 2, 3, 4, 5)
print(first) # 1
print(middle) # [2, 3, 4] (注意 middle 是列表)
print(last) # 5
# 函数返回多个值(本质是返回一个元组)
def get_min_max(numbers):
return min(numbers), max(numbers)
min_val, max_val = get_min_max([5, 2, 8, 1, 9])
print(min_val, max_val) # 1 9
4. 元组的排序
由于元组是不可变的,因此没有像列表的 sort() 那样的原地排序方法。要对元组排序,需要借助内置函数 sorted(),它会返回一个新的列表。如果需要元组结果,可以再将其转换为元组。
4.1 使用 sorted() 函数
sorted() 函数接受一个可迭代对象(如元组),返回一个按升序排列的新列表。
python
unsorted_tuple = (5, 2, 8, 1, 9)
# 升序排序(默认)
sorted_list = sorted(unsorted_tuple)
print(sorted_list) # [1, 2, 5, 8, 9]
print(type(sorted_list)) # <class 'list'>
# 将排序后的列表转换回元组
sorted_tuple = tuple(sorted_list)
print(sorted_tuple) # (1, 2, 5, 8, 9)
print(type(sorted_tuple)) # <class 'tuple'>
4.2 降序排序
通过 reverse=True 参数实现降序。
python
numbers = (3, 1, 4, 1, 5, 9)
descending_list = sorted(numbers, reverse=True)
descending_tuple = tuple(descending_list)
print(descending_tuple) # (9, 5, 4, 3, 1, 1)
4.3 按特定规则排序(使用 key 参数)
key 参数允许你指定一个函数,用于从每个元素中提取比较键。
python
# 按字符串长度排序
words = ('apple', 'fig', 'banana', 'kiwi')
sorted_by_length = tuple(sorted(words, key=len))
print(sorted_by_length) # ('fig', 'kiwi', 'apple', 'banana')
# 按元组中第二个元素排序(例如,按成绩排序)
students = (('Alice', 88), ('Bob', 92), ('Charlie', 85))
sorted_students = tuple(sorted(students, key=lambda x: x[1]))
print(sorted_students)
# (('Charlie', 85), ('Alice', 88), ('Bob', 92))
4.4 原地排序的替代方案
如果你确实需要"原地"修改一个变量指向的元组,可以重新赋值。
python
my_data = (5, 1, 3)
# 无法执行 my_data.sort()
# 但可以:
my_data = tuple(sorted(my_data))
print(my_data) # (1, 3, 5)
5. 元组的常用方法与操作
5.1 查找与计数
python
t = (1, 2, 3, 2, 4, 2)
# count(x) - 返回元素 x 在元组中出现的次数
print(t.count(2)) # 3
print(t.count(5)) # 0
# index(x[, start[, end]]) - 返回元素 x 第一次出现的索引,找不到则引发 ValueError
print(t.index(3)) # 2
print(t.index(2)) # 1
print(t.index(2, 2)) # 3 (从索引2开始找)
# print(t.index(5)) # ValueError: tuple.index(x): x not in tuple
5.2 成员测试
python
colors = ('red', 'green', 'blue')
print('green' in colors) # True
print('yellow' not in colors) # True
5.3 长度与最值
python
data = (45, 12, 89, 33)
print(len(data)) # 4
print(min(data)) # 12
print(max(data)) # 89
print(sum(data)) # 179
5.4 连接与重复
python
# 连接
t1 = (1, 2)
t2 = (3, 4)
t3 = t1 + t2
print(t3) # (1, 2, 3, 4)
# 重复
t4 = ('Hi',) * 3
print(t4) # ('Hi', 'Hi', 'Hi')
6. 元组的应用场景
- 函数返回多个值:这是元组最经典的用法。
- 字典的键:因为元组不可变,它可以作为字典的键,而列表不行。
- 保护数据:确保一组数据在程序运行过程中不会被意外修改。
- 异构数据记录 :例如,用元组
(name, age, city)表示一个人的信息。 - 参数传递 :
*args收集可变位置参数时就是一个元组。
7. 总结
- 创建 :使用
()或tuple(),单元素元组必须加逗号。 - 特性 :有序、可索引、可切片、不可变。
- 遍历 :使用
for、while、解包等方式。 - 排序 :使用
sorted()函数生成新列表,再转换为元组。 - 选择:当数据不需要修改时,优先使用元组;需要动态增删改时,使用列表。
掌握元组的使用能让你写出更安全、更高效的 Python 代码。