Python 常用数据类型相同点、差异与使用指南

发布时间:2026/10/8 8:30:42
Python 常用数据类型相同点、差异与使用指南 前言Python 的内置类型看起来不多但真到选型时很多人还是靠感觉反正 list 能放东西dict 也能放东西那就随便挑一个。结果代码能跑却在几处细节上悄悄出问题——比如拿 list 当字典的键、拿 tuple 期待它「可变」、把字符串当字符数组去改。要避免这些得先抓住几个共同点它们都是对象都支持len()、in、迭代都遵循统一的类型协议。再抓住几个差异点可变还是不可变、有没有顺序、能不能哈希、允许不允许重复、能不能按下标访问。这几个属性的组合基本决定了某个容器适合什么、不适合什么。本文用一张大表把差异摊开再逐个解释这些属性在实际编码中意味着什么最后给出选型指南。示例均为 Python 3 写法。顺带说一句Python 2 已于 2020 年 1 月 1 日停止维护它独有的unicode、basestring、long类型在 Python 3 里都不存在统一成了str和int。一、一张大表横向对比类型可变有序可哈希允许重复下标访问典型用途int否不适用是不适用不适用计数、编号float否不适用是不适用不适用测量值、比例bool否不适用是不适用不适用标志位str否是是是是文本bytes否是是是是二进制数据bytearray是是否是是可变的二进制缓冲list是是否是是有序集合、待处理队列tuple否是通常情况下是是定长记录、字典的键range否是是否是惰性数字序列dict是插入序否键唯一按 key按名查找、分组set是无序否否不适用去重、集合运算frozenset否无序是否不适用需要可哈希的集合表里有几个「不适用」值得说明数字类型没有「顺序」和「下标」的概念因为它们不是容器dict 和 set 没有整数下标只能按 key 或按哈希定位。二、四个关键属性的含义可变性mutability可变对象创建后能改内容不可变对象不能。判断标准是「能不能不新建对象就改变值」。lst.append(1)不新建对象所以 list 可变s a会新建字符串所以 str 不可变。不可变带来的好处是安全——对象一旦造好就不会被别的代码偷偷改掉适合当字典的键、适合当函数默认值。代价是每次「修改」都要造新对象。有序性order这里的「有序」指有没有稳定的位置概念。str、list、tuple 有下标是真正有序的set 和 frozenset 无序遍历顺序不保证dict 从 Python 3.7 起保证按插入顺序遍历3.6 里这个行为是 CPython 的实现细节不要依赖。注意 dict 的「保序」指的是插入顺序不是排序——它不会因为键是数字就自动从小到大排。可哈希性hashability一个对象可哈希意味着它有一个在整个生命周期内不变的哈希值并且能与其他对象比较相等。可哈希的对象才能当 dict 的键、放进 set。经验规则是可变容器一律不可哈希。list、dict、set 都不能当键tuple 和 frozenset 可以——但前提是它们里面的元素也都可哈希。能否重复list、tuple、str 允许重复set、frozenset 不允许dict 的值可以重复键不能。三、这些差异带来的实际后果第一能不能当字典的键。下面的例子说明规则怎么用。# 适用于 Python 3.8d {}d[(1, 2)] 点 A # tuple 可哈希可以当键d[frozenset({1, 2})] 集合 # frozenset 可哈希可以print(d[(1, 2)]) # 点 A# d[[1, 2]] x # TypeError: unhashable type: list# d[{1, 2}] x # TypeError: unhashable type: set# 含可变元素的 tuple 也不可哈希# d[(1, [2, 3])] x # TypeError: unhashable type: list第二哈希相等的对象在集合里只算一个。这是很多「去重去不干净」或「数量对不上」问题的来源。# 适用于 Python 3.8s {1, 1.0, True}print(len(s)) # 1三者在哈希和相等判断上视为同一个print(s {1}) # True# 字符串和数字是不同类型不会互相顶掉t {1, 1}print(len(t)) # 2第三「不可变」和「不可变容器里的内容」是两回事。tuple 本身不可变但如果它装着 list那个 list 是可以改的。语言规范的说法是不可变容器保证的是「直接包含的引用」不变不保证这些引用指向的对象不变。# 适用于 Python 3.8t (1, [2, 3])t[1].append(4) # 合法改的是里面的 listprint(t) # (1, [2, 3, 4])# t[1] [9] # TypeError不能给 tuple 的元素重新赋值第四不同类型之间不能随便比较大小。Python 3 里1 a直接抛TypeErrorPython 2 里不同类型的比较是按类型名排序的这也是 2 和 3 的一大差异。四、怎么选一张决策表你的需求选它理由一条固定不变的记录tuple不可变、可解包、可哈希需要按名字取字段的记录collections.namedtuple 或 dataclass可读性会不断增删的有序集合list尾部增删均摊 O(1)只读的有序集合tuple语义明确防止误改按 key 找值dict平均 O(1) 查找去重set插入即去重需要能当键的集合frozenset不可变所以可哈希一段数字区间range惰性不占内存需要改的字节缓冲bytearray原地修改二进制数据只读bytes不可变、可哈希一个实用的心法先问「要不要改」再问「要不要按名字查」最后问「要不要唯一」。三个问题的答案组合起来容器基本就定了。常见坑点以为「不可变的 tuple」里面的东西也改不了。❌ 把一条含列表的记录塞进 tuple以为整条就此冻结。✅ tuple 只保证元素引用不变要真正不可变里面的元素也得是不可变对象比如把内层 list 换成 tuple。把 str 当成可以就地修改的字符数组。❌s[0] H—— 抛TypeError: str object does not support item assignment。✅ 字符串不可变用切片或replace造新串需要频繁改字符时先转成list再.join回去。用 list 或 set 当字典的键。❌d[[1, 2]] x抛TypeError: unhashable type: list。✅ 转成tuple或frozenset再当键。忽略了1、1.0、True在集合里是同一个人。❌ 用集合统计「不同取值有多少种」时混入了布尔值和数值数量比预期少。✅ 统计前统一类型或改用「类型 值」的元组当元素{(type(x).__name__, x) for x in data}。以为 set 会保持某种顺序。❌ 依赖set的遍历顺序做输出换个数据就变了。✅ 输出前显式排序sorted(s)需要保序去重用dict.fromkeys。把 range 当成真的列表用。❌range(3).append(5)—— range 没有append它不可变。✅ range 只用来生成序列需要可变就list(range(3))。不同类型之间比较大小。❌1 a在 Python 3 里抛TypeErrorPython 2 里能比较属于老代码迁移时的隐藏坑。✅ 比较前统一类型或先判断类型再决定比较方式。用比较浮点数。❌0.1 0.2 0.3结果是False浮点二进制表示无法精确表达这些十进制小数。✅ 用math.isclose(a, b)做近似比较或改用decimal.Decimal处理需要精确十进制运算的场景。总结属性可变的代表不可变的代表线性序列list、bytearraystr、bytes、tuple键值映射dict无内置不可变 dict集合setfrozenset数字无int、float、bool均不可变记住三条判据就够了可变的东西不能当键有序只保证位置稳定不代表会排序不可变容器的不可变性只作用到直接子元素。选型时先定可变性再定查法最后定唯一性比死记硬背每张表都管用。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询