第九篇:list 与 tuple——有序集合的增删改查、切片、排序详解
前言
Python 提供了多种内置数据结构,其中**列表(list)和元组(tuple)**是最常用的有序集合。本文将从零开始全面讲解 list 和 tuple 的各种操作:增删改查、切片、排序方法,以及两者之间的核心区别和选择策略。
列表(list)基础
什么是列表?
列表是 Python 中最灵活的数据结构之一,可以存储任意类型的元素,支持动态扩容。
# 创建空列表
empty = []
empty_alt = list()
# 创建含初始元素的列表
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True, None]
# 列表可以嵌套
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
len() 函数
print(len([1, 2, 3])) # 3
print(len([])) # 0
print(len([[1, 2], [3, 4]])) # 2
list 的基本操作
索引访问
fruits = ["apple", "banana", "cherry", "date"]
# 正向索引从 0 开始
print(fruits[0]) # apple
print(fruits[2]) # cherry
# 负向索引从 -1 开始
print(fruits[-1]) # date
print(fruits[-2]) # cherry
# ❌ 索引越界抛出异常
# print(fruits[10]) # IndexError!
切片操作
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 基本切片 [start:end](左闭右开)
print(nums[2:5]) # [2, 3, 4]
print(nums[:3]) # [0, 1, 2]
print(nums[7:]) # [7, 8, 9]
# 步长参数 [start:end:step]
print(nums[::2]) # [0, 2, 4, 6, 8]
print(nums[1::2]) # [1, 3, 5, 7, 9]
# 反转列表
print(nums[::-1]) # [9, 8, 7, ..., 0]
# 用切片复制列表
copy = nums[:] # 浅拷贝
添加元素
fruits = ["apple", "banana"]
# append():末尾添加单个元素
fruits.append("cherry")
# insert():指定位置插入
fruits.insert(0, "avocado")
# extend():批量追加多个元素
fruits.extend(["date", "elderberry"])
删除元素
fruits = ["apple", "banana", "cherry", "date"]
# remove():按值删除第一个匹配项
fruits.remove("banana")
# pop():按索引删除并返回值
last = fruits.pop() # 弹出最后一个
first = fruits.pop(0) # 弹出索引 0
# del:按索引或切片删除
del fruits[0]
del fruits[1:3] # 删除多个
修改元素
fruits = ["apple", "banana", "cherry"]
fruits[1] = "blueberry"
fruits[0:2] = ["apricot", "blackberry"]
查找与计数
scores = [85, 92, 85, 78, 92, 85]
print(scores.index(92)) # 1 — 第一次出现的位置
print(scores.count(85)) # 3
print(85 in scores) # True
print(100 not in scores) # True
列表排序
sort() 方法 vs sorted() 函数
| 特性 | list.sort() |
sorted(iterable) |
|---|---|---|
| 返回值 | None(原地排序) |
新列表(原列表不变) |
| 适用对象 | 仅列表 | 任何可迭代对象 |
# sort() — 原地排序
nums = [3, 1, 4, 1, 5, 9, 2, 6]
nums.sort()
print(nums) # [1, 1, 2, 3, 4, 5, 6, 9]
# sorted() — 返回新列表
original = [3, 1, 4, 1, 5, 9, 2, 6]
new_nums = sorted(original)
print(new_nums) # [1, 1, 2, 3, 4, 5, 6, 9]
print(original) # 原列表不变
reverse 参数
nums.sort(reverse=True) # 逆序
result = sorted(names, reverse=True)
key 参数:自定义排序规则
# 按字符串长度排序
words = ["banana", "pie", "apple", "kiwi"]
words.sort(key=len)
# ['pie', 'kiwi', 'apple', 'banana']
# 忽略大小写排序
cities = ["beijing", "Beijing", "SHANGHAI"]
cities.sort(key=str.lower)
# 按字典字段排序
students = [{"name": "A", "score": 92}, {"name": "B", "score": 88}]
students.sort(key=lambda x: x["score"])
稳定性
Python 排序是稳定排序——相等元素的相对顺序不变:
pairs = [("Alice", 3), ("Bob", 1), ("Charlie", 3)]
pairs.sort(key=lambda x: x[1])
# Alice 在 Charlie 前,排序后仍保持此顺序
列表推导式
# 基本形式
squares = [x ** 2 for x in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]
# 带条件的推导式
evens = [x for x in range(1, 11) if x % 2 == 0]
print(evens) # [2, 4, 6, 8, 10]
# 双重循环
colors = ["red", "green", "blue"]
sizes = ["S", "M", "L"]
products = [f"{color}-{size}" for color in colors for size in sizes]
# 列表推导式通常比 append 快 20%-40%
元组(tuple)
创建元组
empty = ()
one_element = (42,) # 注意逗号!
multi = (1, 2, 3)
mixed = (1, "hello", 3.14)
tup = 1, 2, 3 # 隐式元组
不可变性
point = (10, 20)
# point[0] = 15 # TypeError! 不能修改
# point.append(...) # AttributeError!
# 但元组中可以包含可变对象
container = ([1, 2], [3, 4])
container[0].append(5) # ✅ 允许!列表本身可变
print(container) # ([1, 2, 5], [3, 4])
应用场景
# 场景一:返回多个值
def divide(a, b):
return a // b, a % b
q, r = divide(10, 3)
# 场景二:作为字典键(不可变保证哈希安全)
location_map = {("北京", 39.9, 116.4): "首都机场"}
# 场景三:保护数据不被修改
RGB_COLOR = (255, 99, 71)
data_tuple = tuple(data_list) # 列表转元组
list vs tuple 对比
| 特性 | list | tuple |
|---|---|---|
| 语法 | [1, 2, 3] |
(1, 2, 3) |
| 可变性 | ✅ 可变 | ❌ 不可变 |
| 内存 | 略高(预留空间) | 略低(固定大小) |
| 速度 | 略慢 | 略快(优化更好) |
| 安全性 | 低 | 高 |
| 可哈希 | ❌ 不能作为 dict 键 | ✅ 可以作为 dict 键 |
| 适用 | 频繁增删改 | 固定不变的数据 |
何时用哪个?
# ✅ list:待办事项会变化
todo_items = []
# ✅ tuple:颜色坐标不会变
RGB_COLOR = (255, 99, 71)
COORDINATE = (39.9, 116.4)
DATE = (2026, 9, 9)
# namedtuple 获得更清晰的语义
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)
print(p.x) # 10
实战示例
成绩管理
scores = []
while True:
name = input("学生姓名(quit 退出):")
if name == "quit": break
score = int(input("分数:"))
scores.append((name, score))
scores.sort(key=lambda x: x[1], reverse=True)
for i, (name, score) in enumerate(scores, 1):
print(f"{i}. {name}: {score} 分")
avg = sum(s for _, s in scores) / len(scores)
print(f"平均分:{avg:.1f}")
去重并保持顺序
def unique_ordered(items):
seen = set()
result = []
for item in items:
if item not in seen:
seen.add(item)
result.append(item)
return result
print(unique_ordered([3, 1, 4, 1, 5, 9, 2, 6, 5]))
# [3, 1, 4, 5, 9, 2, 6]
矩阵运算
rows, cols = 3, 4
matrix = [[0 for _ in range(cols)] for _ in range(rows)]
for i in range(min(rows, cols)):
matrix[i][i] = 1
transposed = [[matrix[j][i] for j in range(rows)] for i in range(cols)]
总结
本文涵盖了 list 和 tuple 的核心知识:
- list 基础 — 创建、len()、索引访问
- 增删改查 — append/insert/extend/remove/pop/del/index/count
- 切片 — [start:end:step]、反转、浅拷贝
- 排序 — sort() vs sorted(),reverse 和 key 参数
- 列表推导式 — 简洁高效的创建方式
- tuple 不可变性 — 适合保护数据和作为 dict 键
- list vs tuple — 可变用 list,不可变用 tuple
- 实用技巧 — 解包赋值、namedtuple、矩阵操作
下一篇文章将深入讲解 dict 与 set:字典的键值对操作与集合的去重特性。
本文是 Python 教程系列的第九篇。
