Python 容器学习笔记:列表、字典、元组与集合
单个变量只能保存一个对象,而真实程序通常需要处理一组数据。Python 提供了列表、字典、元组和集合等容器类型,分别适用于顺序存储、键值映射、固定数据和去重查询等场景。本文重点复盘列表与字典,并对四类容器进行比较。
一、什么是容器
容器是能够同时保存多个数据的对象。例如,记录五名学生的成绩时,如果分别创建五个变量,后续统计和遍历会很麻烦:
score_1 = 88
score_2 = 92
score_3 = 75
使用列表可以把同类数据集中管理:
scores = [88, 92, 75]
Python 中常见的四种容器如下:
| 容器 | 主要特点 | 适用场景 |
|---|---|---|
list | 有序、可变、可重复 | 按顺序保存一组数据 |
dict | 键值映射、键唯一 | 根据名称或编号查找信息 |
tuple | 有序、不可变 | 保存不应被修改的数据 |
set | 无重复元素、快速查询 | 去重、成员判断、集合运算 |
二、列表的创建与索引
列表使用方括号创建,可以保存不同类型的数据:
numbers = [10, 20, 30]
mixed = [1, "Python", True]
empty = []
还可以使用 list() 将其他可迭代对象转换为列表:
numbers = list(range(5)) # [0, 1, 2, 3, 4]
letters = list("abc") # ["a", "b", "c"]
列表索引从 0 开始,负数索引表示从末尾向前查找:
scores = [88, 92, 75, 60, 100]
print(scores[0]) # 88
print(scores[-1]) # 100
print(scores[-2]) # 60
print(len(scores)) # 5
长度为 5 的列表,最大正索引是 4。访问 scores[5] 会触发 IndexError。获取最后一个元素时,推荐直接使用 scores[-1]。
三、列表的增删改查
列表是可变容器,创建后可以继续修改。
1. 添加元素
numbers = [1, 2, 3]
numbers.append(4) # 末尾添加一个元素
numbers.insert(0, 0) # 在指定位置插入
numbers.extend([5, 6]) # 批量添加多个元素
append() 和 extend() 容易混淆:
data = [1, 2]
data.append([3, 4]) # [1, 2, [3, 4]]
data = [1, 2]
data.extend([3, 4]) # [1, 2, 3, 4]
append() 把整个对象作为一个元素加入列表;extend() 则依次加入另一个可迭代对象中的元素。
2. 删除元素
numbers = [10, 20, 30, 20]
numbers.remove(20) # 按值删除第一个 20
last = numbers.pop() # 删除并返回最后一个元素
del numbers[0] # 按索引删除
numbers.clear() # 清空列表
remove(x) 在找不到元素时会触发 ValueError,可以先使用 x in numbers 判断。pop() 会返回被删除的元素,适合“取出并删除”的场景。
3. 修改与查询
scores = [88, 92, 75]
scores[1] = 95
print(88 in scores) # True
print(scores.index(75)) # 2
print(scores.count(88)) # 1
index() 返回元素第一次出现的位置,找不到时会报错;count() 用于统计元素出现次数。
四、列表切片
切片可以一次获取列表中的一段数据,基本语法为:
列表[起始位置:结束位置:步长]
切片遵循“包含起始位置、不包含结束位置”的左闭右开规则:
numbers = list(range(10))
print(numbers[2:5]) # [2, 3, 4]
print(numbers[:3]) # [0, 1, 2]
print(numbers[-3:]) # [7, 8, 9]
print(numbers[::2]) # [0, 2, 4, 6, 8]
print(numbers[::-1]) # 反转列表
切片会创建一个浅拷贝:
original = [1, 2, 3]
copy_list = original[:]
copy_list[0] = 99
print(original) # [1, 2, 3]
而 copy_list = original 只是让两个变量引用同一个列表,通过任意一个变量修改内容都会影响另一个变量。需要注意,浅拷贝只能复制外层容器,嵌套的可变对象仍可能被共享。
五、字典:通过键查找值
列表按照位置访问数据,字典则按照键访问对应的值:
scores = {
"张三": 88,
"李四": 92,
"王五": 75,
}
print(scores["张三"]) # 88
字典适合通讯录、配置项、商品信息和学生成绩等“名称—数据”映射场景。
字典的键必须是可哈希对象,字符串、整数以及只包含可哈希元素的元组通常可以作为键;列表、字典和集合不能作为键。键不能重复,重复赋值会覆盖原来的值。
六、字典的增删改查
为字典赋值时,键不存在表示新增,键已存在表示修改:
scores = {"张三": 88}
scores["李四"] = 92 # 新增
scores["张三"] = 90 # 修改
读取字典值有两种常见方式:
print(scores["张三"])
print(scores.get("赵六"))
print(scores.get("赵六", 0))
使用方括号访问不存在的键会触发 KeyError;get() 可以返回 None 或指定的默认值,因此在不确定键是否存在时更加安全。不过,如果缺少该键本身代表数据错误,直接使用方括号也能帮助程序尽早暴露问题。
删除字典元素可以使用 del 或 pop():
data = {"a": 1, "b": 2}
del data["a"]
value = data.pop("b")
missing = data.pop("c", None)
批量合并字典可以使用 update()。如果两个字典包含相同的键,新值会覆盖旧值:
config = {"theme": "light", "font_size": 14}
config.update({"theme": "dark", "language": "zh"})
七、字典遍历
字典可以分别遍历键、值或键值对:
scores = {"张三": 88, "李四": 92}
for name in scores:
print(name)
for score in scores.values():
print(score)
for name, score in scores.items():
print(f"{name}考了{score}分")
实际开发中,items() 是最常用的遍历方式,因为它可以同时得到键和值。
八、元组与集合
元组与列表相似,但创建后不能修改:
point = (3, 4)
print(point[0])
single = (5,) # 单元素元组必须保留逗号
坐标、RGB 颜色等固定数据适合使用元组。元组还可以在满足可哈希条件时作为字典的键。
集合主要用于去重和成员判断:
names = ["张三", "李四", "张三", "王五"]
unique_names = set(names)
print("张三" in unique_names) # True
集合还支持交集、并集和差集:
a = {1, 2, 3}
b = {3, 4, 5}
print(a & b) # {3}
print(a | b) # {1, 2, 3, 4, 5}
print(a - b) # {1, 2}
列表的成员查找平均需要逐个比较,时间复杂度为 O(n);字典按键查找和集合成员判断的平均时间复杂度通常为 O(1)。因此,当数据量较大且需要频繁判断元素是否存在时,集合通常比列表更合适。
九、嵌套容器
真实数据经常由多层容器组成。例如,可以用列表保存多名学生,再用字典描述每名学生:
students = [
{"name": "张三", "score": 88},
{"name": "李四", "score": 92},
{"name": "王五", "score": 75},
]
print(students[0]["score"]) # 88
for student in students:
print(student["name"])
best = max(students, key=lambda student: student["score"])
print(best)
students[0]["score"] 包含两层访问:先从列表中取出第一个字典,再通过 "score" 获取对应值。理解这种逐层访问方式,是后续处理 JSON、接口响应和数据集的基础。
十、如何选择容器
| 需求 | 推荐容器 |
| 数据有顺序、允许重复且需要修改 | list |
| 根据名称或编号查找数据 | dict |
| 数据固定不变 | tuple |
| 去重或频繁判断成员是否存在 | set |
可以用三个问题帮助选择:数据是否需要修改?是否需要通过名称查值?是否主要用于去重或成员判断?
总结
列表适合有序数据,字典适合键值映射,元组适合固定数据,集合适合去重和快速查询。掌握容器时,不仅要会调用方法,还要理解每种结构的数据组织方式。
需要重点区分:
-
append()添加一个对象,extend()批量添加元素; -
remove()按值删除,pop()和del可以按位置删除; -
切片左闭右开,
[::-1]可以反转序列; -
字典的
[]访问可能触发KeyError,get()可以设置默认值; -
b = a共享同一个列表,b = a[:]创建浅拷贝; -
大量成员查询和去重任务优先考虑集合。
建议通过学生成绩、通讯录、词频统计和名单去重等小案例反复练习,逐渐形成根据业务需求选择容器的习惯。
更多推荐
所有评论(0)