09.Python 容器详解:从基础到进阶的全面指南
摘要:本文系统梳理了 Python 容器的概念、分类与使用好处,深入讲解了列表、元组、集合、字典以及 collections 模块中的 deque、namedtuple、Counter、defaultdict、OrderedDict 等高级容器,并总结了增删改查、遍历、切片、推导式等核心操作,最后给出了容器选择与学习建议,帮助读者全面掌握 Python 容器知识体系。
目录
1. 什么是容器
在 Python 中,容器(Container)是一种用于存放和管理多个元素的数据结构。它就像现实生活中的"容器"一样——一个箱子可以装很多物品,一个文件夹可以放很多文件。Python 容器允许我们将多个值组织在一起,方便统一管理和操作。
从技术角度看,容器是实现了特定协议(如 __contains__、__iter__、__len__ 等方法)的对象,它们能够容纳其他对象,并提供访问、遍历和修改这些对象的能力。
简单理解:变量好比一个"停车位",只能放一辆车;而容器好比一个"停车场",可以同时停放多辆车,并且能对它们进行统一管理。
2. 容器的分类
Python 中的容器可以从多个维度进行分类,最常见的是按数据组织方式分为以下三大类:
| 分类 | 包含类型 | 核心特征 |
|---|---|---|
| 序列类型 | 列表(list)、元组(tuple)、范围(range)、字符串(str)、字节序列(bytes、bytearray) | 元素按顺序排列,支持索引和切片操作 |
| 集合类型 | 集合(set)、冻结集合(frozenset) | 元素无序且唯一,支持集合运算(交并差) |
| 映射类型 | 字典(dict) | 以键值对形式存储数据,通过键快速查找值 |
此外,还可以按"可变性"来区分:
- 可变容器:列表(list)、集合(set)、字典(dict)、字节数组(bytearray)等,创建后可以增删改元素。
- 不可变容器:元组(tuple)、冻结集合(frozenset)、字符串(str)、字节序列(bytes)等,一旦创建就不能修改内容。
Python 标准库中的 collections 模块还提供了许多高级容器,如 deque(双端队列)、namedtuple(命名元组)、Counter(计数器)、defaultdict(默认值字典)、OrderedDict(有序字典)等,它们在特定场景下比基础容器更加高效和便捷。
3. 使用容器的好处
在日常编程中,使用容器能带来以下显著优势:
- 组织性强:将相关数据放在一个容器中,代码结构更清晰,逻辑更容易理解。比如用一个列表存放所有学生的成绩,而不是定义几十个零散变量。
- 操作便捷:容器提供了丰富的内置方法(增删改查、排序、反转、过滤等),能大幅减少手写代码量,提升开发效率。
- 内存高效:Python 容器在底层做了大量优化,相比手动管理分散的变量,容器对内存的利用率更高,访问速度也更快。
- 可迭代性:所有容器都支持迭代,可以方便地用
for循环遍历,结合推导式、map/filter等高阶函数进行批量处理。 - 类型丰富,按需选择:不同容器有各自的优势——需要去重用集合,需要快速查找用字典,需要保持顺序用列表。根据场景选择合适的容器,能极大优化程序性能。
- 代码可维护性:统一的容器接口让代码更容易被他人理解和维护,也方便进行单元测试和调试。
4. 常用容器详解
4.1 列表(list)
列表是 Python 中最常用的可变序列容器,用方括号 [] 表示。它可以存放任意类型的元素,甚至是混合类型,并且支持动态扩容。
创建列表:
# 空列表
empty = []
包含元素的列表
fruits = ["apple", "banana", "cherry"]
使用 list() 构造函数
numbers = list(range(1, 6)) # [1, 2, 3, 4, 5]
列表推导式
squares = [x ** 2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
列表的特点:
- 元素有序,按插入顺序排列。
- 支持索引和切片:
fruits[0]、fruits[1:3]。 - 可变:可以随时添加、删除、修改元素。
- 允许重复元素。
- 时间复杂度:索引访问 O(1),末尾追加 O(1),插入/删除 O(n)。
适用场景:需要维护一组有序数据,且经常进行增删改操作的场景,如待办事项列表、用户记录列表、数据处理管道中的中间结果等。
4.2 元组(tuple)
元组是不可变的序列容器,用小括号 () 表示(也可省略括号)。一旦创建,元素就不能被修改、添加或删除。
# 创建元组
point = (3, 5)
colors = "red", "green", "blue" # 括号可省略
单元素元组(注意逗号)
single = (42,)
嵌套元组
matrix = ((1, 2), (3, 4))
元组的特点:
- 不可变:保证了数据的安全性,适合作为常量集合使用。
- 有序,支持索引和切片。
- 占用内存比列表小,创建速度更快。
- 可以作为字典的键(列表不能)。
- 支持"拆包"(unpacking):
x, y = point。
适用场景:表示固定不变的数据结构(如坐标、RGB 颜色值)、函数返回多个值、作为字典的键、保护不希望被意外修改的数据。
4.3 集合(set)
集合是无序且元素唯一的可变容器,用花括号 {} 或 set() 创建。它基于哈希表实现,查找速度极快。
# 创建集合
empty_set = set() # 注意:{} 创建的是空字典
numbers = {1, 2, 3, 4}
自动去重
unique = {1, 2, 2, 3, 3, 3} # {1, 2, 3}
从列表去重
my_list = [1, 2, 2, 3, 3, 3]
unique_list = list(set(my_list)) # [1, 2, 3]
集合的特点:
- 元素唯一:自动去重,这是集合最重要的特性。
- 无序:不能通过索引访问元素。
- 可变:可以添加和删除元素。
- 元素必须是可哈希的(不可变类型),因此列表不能作为集合元素。
- 支持数学集合运算:并集(
|)、交集(&)、差集(-)、对称差集(^)。 - 查找复杂度 O(1),非常高效。
适用场景:数据去重、成员资格快速检查(判断某元素是否存在)、集合运算(如求共同好友、差集筛选)、去除重复 URL 等。
4.4 字典(dict)
字典是 Python 中最核心的映射类型容器,以键值对(key-value)形式存储数据,用花括号 {} 表示。它是 Python 中查找效率最高的数据结构之一。
# 创建字典
person = {"name": "张三", "age": 28, "city": "北京"}
使用 dict() 构造函数
config = dict(host="localhost", port=8080)
字典推导式
squares = {x: x ** 2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
字典的特点:
- 键值对存储:每个键(key)映射到一个值(value)。
- 键必须唯一且可哈希(不可变类型),值可以是任意类型。
- Python 3.7+ 字典保持插入顺序。
- 可变:可以增删改键值对。
- 查找、插入、删除复杂度均为 O(1)。
适用场景:需要快速根据键查找对应值的场景,如用户信息存储、配置管理、缓存系统、计数器、JSON 数据处理等。
4.5 其他高级容器(collections 模块)
Python 标准库中的 collections 模块提供了一些功能更强大的容器类型,是对基础容器的补充和扩展。
deque(双端队列)
deque(发音为 "deck")是双向队列,支持在两端高效地添加和删除元素,复杂度为 O(1),而列表在头部操作是 O(n)。
from collections import deque
dq = deque([1, 2, 3])
dq.append(4) # 右端添加:[1, 2, 3, 4]
dq.appendleft(0) # 左端添加:[0, 1, 2, 3, 4]
dq.pop() # 右端删除:返回 4
dq.popleft() # 左端删除:返回 0
适用场景:实现队列和栈、滑动窗口、最近使用记录(LRU 缓存)等。
namedtuple(命名元组)
namedtuple 是元组的子类,允许通过名称(而不仅是索引)访问字段,让代码更具可读性。
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)
print(p.x) # 10
print(p.y) # 20
仍然是元组,支持索引和拆包
print(p[0]) # 10
适用场景:代替简单类、表示坐标/颜色/RGB 等轻量数据结构、从 CSV 或数据库读取记录。
Counter(计数器)
Counter 是字典的子类,专门用于统计元素出现的次数。
from collections import Counter
words = ["a", "b", "a", "c", "b", "a"]
count = Counter(words)
print(count) # Counter({'a': 3, 'b': 2, 'c': 1})
print(count["a"]) # 3
print(count.most_common(2)) # [('a', 3), ('b', 2)]
适用场景:词频统计、字符频率分析、投票计数、数据分布统计。
defaultdict(默认值字典)
defaultdict 是字典的子类,当访问不存在的键时,会自动生成一个默认值,避免 KeyError 异常。
from collections import defaultdict
用 list 作为默认工厂
groups = defaultdict(list)
groups["语文"].append("张三")
groups["语文"].append("李四")
print(groups) # defaultdict(<class 'list'>, {'语文': ['张三', '李四']})
没有 KeyError,自动创建空列表
print(groups["数学"]) # []
适用场景:分组操作、构建邻接表、统计多级数据等。
OrderedDict(有序字典)
在 Python 3.7 之前,普通字典不保证插入顺序。OrderedDict 提供了保证顺序的字典实现,并额外提供了 move_to_end() 等方法来重新排列元素。Python 3.7+ 中普通字典已有序,但 OrderedDict 仍保留了这些额外方法。
from collections import OrderedDict
od = OrderedDict()
od["first"] = 1
od["second"] = 2
od["third"] = 3
od.move_to_end("first") # 将 "first" 移到最后
print(od) # OrderedDict([('second', 2), ('third', 3), ('first', 1)])
适用场景:需要精确控制元素顺序的场景、实现 LRU 缓存、保持 JSON 键顺序。
5. 容器的常见操作
Python 容器提供了丰富的内置操作,以下按功能类别进行梳理。
5.1 增删改查(CRUD 操作)
# === 列表 ===
lst = [1, 2, 3]
lst.append(4) # 末尾追加:[1, 2, 3, 4]
lst.insert(1, 99) # 指定位置插入:[1, 99, 2, 3, 4]
lst.extend([5, 6]) # 扩展多个元素:[1, 99, 2, 3, 4, 5, 6]
lst.remove(99) # 删除指定值:[1, 2, 3, 4, 5, 6]
popped = lst.pop(0) # 按索引删除并返回:popped=1, lst=[2, 3, 4, 5, 6]
=== 字典 ===
d = {"a": 1}
d["b"] = 2 # 新增键值对
d["a"] = 10 # 修改值
value = d.get("c", 0) # 安全获取,不存在返回默认值 0
del d["b"] # 删除键值对
d.pop("a") # 删除并返回值
=== 集合 ===
s = {1, 2}
s.add(3) # 添加元素
s.remove(2) # 删除元素(不存在则报错)
s.discard(99) # 安全删除(不存在不报错)
5.2 遍历与迭代
# 遍历列表
for item in [1, 2, 3]:
print(item)
带索引遍历
for i, item in enumerate(["a", "b", "c"]):
print(i, item)
遍历字典
d = {"name": "张三", "age": 28}
for key in d:
print(key)
for key, value in d.items():
print(key, value)
同时遍历多个列表
for a, b in zip([1, 2], ["x", "y"]):
print(a, b)
5.3 切片操作(序列类型)
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[2:5]) # [2, 3, 4] 从索引 2 到 4
print(lst[:3]) # [0, 1, 2] 前三个
print(lst[-3:]) # [7, 8, 9] 后三个
print(lst[::2]) # [0, 2, 4, 6, 8] 步长为 2
print(lst[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 反转
5.4 推导式(Comprehension)
# 列表推导式
squares = [x ** 2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
字典推导式
square_map = {x: x ** 2 for x in range(5)}
集合推导式
unique_lengths = {len(word) for word in ["apple", "banana", "cherry"]}
5.5 排序与反转
# 列表排序
lst = [3, 1, 4, 1, 5, 9]
lst.sort() # 原地排序:[1, 1, 3, 4, 5, 9]
lst.sort(reverse=True) # 降序:[9, 5, 4, 3, 1, 1]
自定义排序
words = ["banana", "apple", "cherry"]
words.sort(key=len) # 按长度排序:['apple', 'banana', 'cherry']
返回新列表
sorted_lst = sorted([3, 1, 2]) # [1, 2, 3]
反转
lst.reverse() # 原地反转
5.6 成员检查
# 检查元素是否存在
fruits = ["apple", "banana", "cherry"]
print("apple" in fruits) # True
print("grape" not in fruits) # True
字典中检查键
d = {"name": "张三"}
print("name" in d) # True
5.7 内置函数
Python 提供了一系列与容器配套使用的内置函数:
len():返回容器中元素的个数。max()/min():返回容器中的最大/最小元素。sum():对数值容器求和。any()/all():判断是否有/所有元素为真。map()/filter():对容器元素进行映射和过滤。zip():将多个容器按位置打包。enumerate():为可迭代对象添加索引。
nums = [1, 2, 3, 4, 5]
print(len(nums)) # 5
print(max(nums)) # 5
print(sum(nums)) # 15
print(any([0, 0, 1])) # True
print(all([1, 2, 3])) # True
map 示例
doubled = list(map(lambda x: x * 2, nums)) # [2, 4, 6, 8, 10]
filter 示例
evens = list(filter(lambda x: x % 2 == 0, nums)) # [2, 4]
5.8 容器之间的转换
# 列表 ↔ 元组
tuple_from_list = tuple([1, 2, 3]) # (1, 2, 3)
list_from_tuple = list((1, 2, 3)) # [1, 2, 3]
列表 ↔ 集合(去重)
unique = list(set([1, 2, 2, 3])) # [1, 2, 3]
列表 ↔ 字典
pairs = [("a", 1), ("b", 2)]
d = dict(pairs) # {'a': 1, 'b': 2}
items = list(d.items()) # [('a', 1), ('b', 2)]
字符串 ↔ 列表
chars = list("hello") # ['h', 'e', 'l', 'l', 'o']
joined = "".join(chars) # "hello"
6. 总结
Python 容器是编程中最基础也最重要的工具之一。本文从是什么、为什么、有哪些、怎么用四个维度系统梳理了容器的核心知识:
- 容器是什么:存放和管理多个元素的数据结构,是组织和操作数据的"容器"。
- 容器的分类:主要分为序列类型(list、tuple)、集合类型(set、frozenset)和映射类型(dict),同时
collections模块提供了 deque、namedtuple、Counter、defaultdict、OrderedDict 等高级容器。 - 为什么用容器:提升代码组织性、操作便捷性、内存效率和可维护性,是编写高质量 Python 代码的基础。
- 容器怎么用:掌握增删改查、遍历迭代、切片、推导式、排序、成员检查、内置函数和类型转换等核心操作,就能应对绝大多数开发场景。
在实际开发中,选择合适的容器至关重要:需要有序可变数据选列表,需要不可变安全数据选元组,需要去重和集合运算选集合,需要快速键值查找选字典。合理运用容器,能让代码更简洁、更高效、更 Pythonic。
建议读者在学习完本文后,动手实践每个容器类型的创建和常用操作,并结合 collections 模块尝试一些高级用法,这样能更快地将理论知识转化为实际编码能力。
更多推荐


所有评论(0)