Python 数据结构终极汇总:从入门到“心中有数”
目录
2.2 浅拷贝(Shallow Copy)—— 只复制第一层
2.3 深拷贝(Deep Copy)—— 复制所有层,彻底独立
前言
到这里,你已经跟 Python 里的五大“数据结构天团”全都见过面了:
字符串(str) —— 文字处理小能手列表(list) —— 能装能改的购物车
元组(tuple) —— 不能改的固定套餐
字典(dict) —— 带标签的储物柜
集合(set) —— 自动去重的神奇袋子
它们就像你工具箱里的五把不同功能的螺丝刀,有的用来拧十字,有的用来拧一字。选对了工具,干活事半功倍;选错了,拧到怀疑人生。
今天这一篇,我们不学新知识,而是把五个家伙拉到一起横向对比——什么时候用谁、各自有什么绝活、互相怎么转换。最后再加一道硬菜:浅拷贝 vs 深拷贝,把“复制”这件事彻底讲透。
看完这篇,你脑子里就有一张完整的“数据结构地图”了。🗺️
一、五大数据结构横向对比
1.1 一张表看懂全部
🧠 背口诀:
要改顺序 → 列表
铁了心不改 → 元组
想按名字查 → 字典
想自动去重 → 集合
只是文字 → 字符串
1.2 各自的核心场景
字符串(str):文本处理、日志拼接、用户输入、文件内容解析。
python
# 拼接用户信息
name = "王小明"
age = 18
msg = f"用户:{name},年龄:{age}岁"
列表(list):有顺序的数据集合、排行榜、待办事项。
python
# 排行榜前五 ranking = ["湖人", "凯尔特人", "勇士", "太阳", "掘金"]
元组(tuple):固定不变的数据、坐标点、数据库一条记录、函数多返回值。
python
# 坐标点 (x, y) position = (39.9042, 116.4074) # 天安门坐标,改不得
字典(dict):带字段名的复杂对象、用户信息、配置参数、缓存数据。
python
# 用户信息
user = {
"id": 1001,
"name": "王小明",
"age": 18,
"roles": ["admin", "editor"]
}
集合(set):去重、交集并集运算、标签系统、好友关系。
python
# 去重
visitors = ["张三", "李四", "张三", "王五", "李四"]
unique = set(visitors) # {"张三", "李四", "王五"}
1.3 互相转换(类型转换全家桶)
python
# 字符串 ↔ 列表(拆字/合字)
s = "hello"
print(list(s)) # ['h', 'e', 'l', 'l', 'o']
print("".join(['h','e'])) # "he"
# 列表 ↔ 元组
lst = [1, 2, 3]
print(tuple(lst)) # (1, 2, 3)
print(list((1,2,3))) # [1, 2, 3]
# 列表 ↔ 集合(去重专用)
lst = [1, 2, 2, 3, 3, 3]
print(set(lst)) # {1, 2, 3}
print(list({1,2,3})) # [1, 2, 3]
# 字典 ↔ 列表(拆键值对)
d = {"a": 1, "b": 2}
print(list(d.keys())) # ['a', 'b']
print(list(d.values())) # [1, 2]
print(list(d.items())) # [('a', 1), ('b', 2)]
第二章:深拷贝 vs 浅拷贝 —— 复制不是“贴标签”
2.1 你以为是复制,其实是“贴标签”
很多新手都会犯一个错误:
python
a = [1, 2, 3] b = a # 这不是复制!是贴了个新标签 b.append(4) print(a) # [1, 2, 3, 4] ← 原列表也被改了! print(b) # [1, 2, 3, 4]
📌 原因:
b = a没有复制列表,只是让b也指向同一个列表。就像一份文件有两个名字,改其中任何一个都改了同一份文件。
2.2 浅拷贝(Shallow Copy)—— 只复制第一层
浅拷贝会复制最外层容器,但容器里面的元素还是指向原来的东西。
python
# 方法一:列表的 copy() original = [1, 2, [10, 20]] new = original.copy() # 方法二:切片 new2 = original[:] # 方法三:list() 构造 new3 = list(original)
浅拷贝的行为:
python
original = [1, 2, [10, 20]] new = original.copy() new[0] = 999 # 改外层 → 不影响原列表 new[2][0] = 888 # 改内层列表 → 原列表也变了! print(original) # [1, 2, [888, 20]] ← 内层被改了! print(new) # [999, 2, [888, 20]]
📌 一句话:浅拷贝只管第一层,里面的子对象还是“共享”的。就像复印了一张户型图,图纸上写了新名字,但房子里面的家具还是同一套。
2.3 深拷贝(Deep Copy)—— 复制所有层,彻底独立
深拷贝会递归复制所有层,新列表和原列表完全没关系,改哪里都不影响对方。
python
import copy original = [1, 2, [10, 20]] new = copy.deepcopy(original) new[0] = 999 new[2][0] = 888 print(original) # [1, 2, [10, 20]] ← 原列表完全不变 print(new) # [999, 2, [888, 20]]
📌 一句话:深拷贝是真正的“克隆”——从头到脚复制一份完整的,互不干扰。
2.4 浅拷贝 vs 深拷贝:一张图看懂
| 浅拷贝 | 深拷贝 | |
|---|---|---|
| 复制层级 | 只复制第一层 | 递归复制所有层 |
| 内层对象 | 共享引用 | 完全独立 |
| 改外层 | 不影响原对象 | 不影响原对象 |
| 改内层 | ✅ 影响原对象! | ❌ 不影响原对象 |
| 性能 | 快 | 慢(递归复制所有层) |
| 适用场景 | 数据简单,或只改最外层 | 数据复杂,需要完全独立 |
python
import copy
original = [1, 2, [3, 4]]
# 浅拷贝
shallow = original.copy()
shallow[2][0] = 999
# 深拷贝
deep = copy.deepcopy(original)
deep[2][0] = 888
print("原列表:", original) # [1, 2, [999, 4]] ← 被浅拷贝影响了
print("深拷贝:", deep) # [1, 2, [888, 4]]
2.5 什么时候用谁?
用浅拷贝:
数据是简单的列表,没有嵌套(里面全是数字/字符串)
你只改最外层的元素,不改内层
你确定“改了不影响原数据”
用深拷贝:
数据有嵌套结构(列表里套列表、字典里套列表)
你要复制后“各改各的”,互不干扰
数据复杂,但你必须保留一份原始数据不动
实际工作中:遇到嵌套数据要独立修改的,直接用 copy.deepcopy() 最稳,别纠结。
🎯 最终汇总表(建议收藏)
| 数据结构 | 可变 | 有序 | 去重 | 适用场景 |
|---|---|---|---|---|
str |
❌ | ✅ | — | 文本处理 |
list |
✅ | ✅ | ❌ | 有顺序的批量数据 |
tuple |
❌ | ✅ | ❌ | 固定不变的数据 |
dict |
✅ | ✅ | 键唯一 | 带标签的复杂对象 |
set |
✅ | ❌ | ✅ | 去重、集合运算 |
| 操作 | 方法 |
|---|---|
| 浅拷贝 | list.copy()、切片[:]、list()、dict.copy() |
| 深拷贝 | copy.deepcopy() |
🧁 结尾
到今天为止,你已经把 Python 里最常用的五种数据结构全盘了一遍。它们就像你手里五张不同的牌——单打独斗各有千秋,组合起来更是威力无穷。
你想想日常里最常见的场景:
python
# 你点外卖
user = {"name": "王小明", "address": "北京市海淀区"} # 字典存用户信息
order_items = ["宫保鸡丁", "米饭", "可乐"] # 列表存购物车
order_tuple = (20260721, "已支付", 45.5) # 元组存订单状态(改不得)
unique_tags = set(["辣", "素食", "辣"]) # 集合自动去重
summary = f"用户{user['name']}点了{len(order_items)}样菜" # 字符串拼输出
你看,一个外卖订单,五种数据结构全用上了。它们不是孤立的,是配合着干的。
今天这篇汇总就像是给你发了一张“数据结构地图”,以后再遇到“存什么、怎么存”的问题,拿出来对照一下,心里就有数了。
想必经过一个多月的数据类型的学习,我们应该对各种数据类型融会贯通,那么在接下来的学习中让我们带着这些数据类型应用到更深处的学习中吧,各位"糕手"
更多推荐




所有评论(0)