当前位置:首页>排行榜>Python 数据容器怎么选?list、tuple、set、dict 一篇讲明白

Python 数据容器怎么选?list、tuple、set、dict 一篇讲明白

  • 更新时间 2026-11-10 21:00:18
Python 数据容器怎么选?list、tuple、set、dict 一篇讲明白

变量只能装一个值,真正写程序得把一堆值装进盒子。
list / str / tuple / set / dict 五种容器,先给一张「怎么选」的表,再给 9 段能直接复制运行的代码,最后把它们拼成一个完整的小程序。
9 段代码在 Python 3.11 下跑通,每段都能单独运行,不依赖上下文。

{} 看着像空集合,其实是空字典;想建空集合,只能写 set()。

这类「看着差不多、用起来完全不一样」的地方,数据容器里特别多。

先记三问:这份数据要不要改、要不要去重、是不是按名字取值。三问下来,用哪个容器就定了。

一、30 秒选容器

容器
有序
可重复
能改
什么时候用
list
是
是
是
要增删、要按下标取
str
是
是
否
文本,只能生成新字符串
tuple
是
是
否
一组不该被改动的记录
set
否
否
是
去重、交并差
dict
按插入顺序
key 不重复
是
按名字取值,没有下标

一句话记:要改选 list,不改选 tuple,去重选 set,按名字存取选 dict。

二、list:要改,就选它

能存不同类型的元素,能增、能删、能改,是默认的万能选手。

s = [56, 12, 90]
s.append(7)
s.insert(1, 30)
s.pop()
print
(s)                  # [56, 30, 12, 90]

for
 item in s:
    print
(item, end=" ")

切片是序列类型的通用技能,str 和 tuple 也能用:

s = [1, 2, 3, 4, 5]
print
(s[0:3])             # [1, 2, 3],含头不含尾
print
(s[3:0:-1])          # [4, 3, 2],步长为负就从右往左
print
(s[::-1])            # 整个反转

解包用 * 把列表拆成一个个元素;推导式则是一行生成新列表,比写循环短得多:

a = [10, 25, 89, 12, 88]
b = [11, 29, 89, 12, 90]

merged = [*a, *b]                      # 解包合并
unique = []
for
 n in merged:
    if
 n not in unique:
        unique.append(n)
print
(unique)                          # 去重,且保留原顺序

print
([i ** 2 for i in range(1, 6)])   # [1, 4, 9, 16, 25]
print
([i for i in a if i > 50])        # [89, 88]

三、str 和 tuple:改不了的两种

字符串和元组都是不可变的:没有 append,也不能 s[0] = "H",所有「修改」其实都是生成一个新对象。

s = "Hello Python"
print
(s[6:])              # Python
print
(s[::-1])            # nohtyP olleH
print
(s.find("Python"))   # 6,找不到返回 -1
print
(s.upper(), s.lower())
print
(s.replace("o", "A"))
print
(s.split(" "))       # ['Hello', 'Python']

元组常用来放「一组不该被改的记录」,只有 count 和 index 两个方法。它真正好用的地方是解包:

t1 = (11, 24, 53, 68, 90, 24, 90)
print
(t1.count(90), t1.index(90))   # 2 4

print
(type((100)), type((100, )))   # 单元素元组,逗号不能省

a, b, *rest = t1                    # * 收集剩下的元素,得到列表
print
(a, b, rest)

x, y = 10, 20
x, y = y, x                         # 交换两个变量,本质是元组解包
print
(x, y)

四、set:去重和交并差

无序、不重复,最擅长「这堆东西里有哪些、两边共有哪些」。

s1 = {"A", "C", "E", "H"}
s2 = {"A", "B", "C", "D"}
print
(s1 - s2)            # 差集:只在 s1 里
print
(s1 | s2)            # 并集:全部
print
(s1 & s2)            # 交集:两边都有

print
(sorted(set([1, 2, 2, 3, 3])))   # 去重
empty = set()             # 空集合只能这么建,{} 是空字典

五、dict:按名字取值

没有下标,靠 key 取值。key 必须是不可变类型(str、int、tuple 都行,list 不行)。

d = {"王林": 670, "李慕婉": 608}
d["韩立"] = 688                     # 增 / 改
print
(d.get("张三", "查无此人"))     # 找不到不报错
print
(list(d.keys()), list(d.values()))

for
 k, v in d.items():
    print
(k, v)

print
(d.pop("王林"))                 # 删除并拿到值

六、把它们拼起来:一个完整的小程序

一组成绩记录,把 tuple 存记录、dict 按名字索引、list 推导式算分、set 数人头,全串起来:

students = (
    ("S001", "王林", 85, 92, 78),
    ("S002", "李慕婉", 92, 88, 95),
    ("S003", "张三", 78, 85, 82),
)

scores = {}
for
 sid, name, chinese, math, english in students:   # 元组解包
    scores[name] = (chinese, math, english)           # dict 按名字存

for
 name, (c, m, e) in scores.items():
    print
(f"{name} 总分 {c + m + e} 平均 {(c + m + e) / 3:.1f}")

chinese = [c for c, m, e in scores.values()]          # 推导式
print
(f"语文平均 {sum(chinese) / len(chinese):.1f}")
print
(f"共 {len(set(scores))} 人")                     # set 去重

到这里,你已经能自己决定「这份数据该装进哪个盒子」,并且写出来跑通了。

七、5 个最容易踩的坑

Warning

下面 5 条,跑一遍这段代码就全懂了:

a = [1, 2, 3]
b = a
b.append(4)
print
("b = a 之后:", a)            # a 也跟着变了

print
(type({}), type(set()))       # {} 是 dict
print
(type((100)), type((100, )))  # 少个逗号,元组就变成 int
  1. 1. b = a不是复制,两个名字指向同一个列表。要副本用 a.copy() 或 a[:]。
  2. 2. {} 是空字典,不是空集合;空集合必须写 set()。
  3. 3. 单元素元组要写 (100, ),(100) 只是加了括号的整数。
  4. 4. str 和 tuple不可变,s[0] = "H" 会直接 TypeError;s.replace(...) 返回的是新对象,原串没变。
  5. 5. dict 的 key 必须不可变,拿 list 或 set 当 key 会报 TypeError;取值用 d.get(k) 比 d[k] 更稳,找不到不会崩。

八、收尾

一句话:容器不是背 API,是先问「这份数据要不要改、要不要去重、要不要按名字取」,答案出来,容器就定了。

这 9 段你都跑通了吗?卡在哪一段,把报错贴到评论区,我看到就回。

觉得有用,顺手点个「在看」,或转给正在入门的朋友。

随机文章