基础篇 · Foundations
lv.1 入门
kp-004
内置数据类型总览
1. 一句话定义
Python 一切皆对象,内置类型可分为数值、序列、映射、集合、布尔/空值五大族,每族又按可变 / 不可变一分为二——这一刀切分了后面大部分行为差异。
2. 为什么重要
"选对容器 + 知道可不可变"是写 Python 的两大日常决策。可变性决定:能否作字典键、传参副作用、是否需要拷贝。本知识点建立全景地图,细节由后续专文展开。
3. 前置知识
kp-003(名字绑定,理解"类型属于对象")。
4. 核心概念(五大族)
| 族 | 不可变 | 可变 | 专文 |
|---|---|---|---|
| 数值 | int float complex bool(int 的子类) | — | — |
| 序列 | str tuple bytes | list bytearray | kp-008 / kp-009 |
| 映射 | — | dict | kp-010 |
| 集合 | frozenset | set | kp-010 |
| 空值 | None(NoneType 唯一实例) | — | — |
其他常用内置:range(不可变序列,惰性)、type、函数也是对象。
5. 原理与机制
可变 vs 不可变的本质:不可变对象的值在创建后不能改变(对它"修改"实际是生成新对象),因此可以安全地被哈希、被共享;可变对象允许原地修改(id 不变、内容变了)。
python
s = "hi"
print(id(s))
s += "!" # 绑定到了新字符串对象
print(id(s)) # id 变了
lst = [1]
print(id(lst))
lst.append(2)
print(id(lst)) # id 不变,内容变了数值精度:int 任意精度(不会溢出);float 是 IEEE 754 双精度,0.1 + 0.2 != 0.3,比较用 math.isclose;需要精确小数(钱)用 decimal.Decimal。
6. 关键事实(模型/图示)
text
┌── 不可变:int float str tuple frozenset bytes range ──► 可哈希,可作 dict 键
对象 ───┤
└── 可变: list dict set bytearray ──► 不可哈希,原地修改type(x) 查类型;isinstance(x, T) 查归属(优先用它,兼顾子类)。
7. 直观类比
不可变对象像铅字(活字印刷):刻好了就只能复制和重排,改一个字要新刻一枚;可变对象像白板:当场擦改,同一块板被所有人引用,谁都别假设它还是上次看到的内容。
8. 实例与案例
python
# dict 键必须可哈希
d = {(1, 2): "ok"} # tuple 作键 ✔
# d = {[1]: "no"} # TypeError: list 不可哈希
# 浮点比较
import math
math.isclose(0.1 + 0.2, 0.3) # True
# 类型转换
int("42"), float("3.5"), str(3), list("abc") # 42, 3.5, '3', ['a','b','c']9. 常见误区
bool是独立类型 —— 它是int的子类,True == 1、False == 0成立。- 用
==比较 float —— 用math.isclose或Decimal。 - 以为
str可以像 list 一样改 —— 字符串不可变,所有"修改"方法都返回新串。 tuple元素不可变 ≠ tuple 深处不可变 ——t = (1, [2]); t[1].append(3)合法且危险(哈希会失败)。
10. 自测题
- 为什么 list 不能作 dict 的键而 tuple 通常可以?
s = "a"; s = s + "b"中id(s)会变吗?说明发生了什么。- 如何安全比较两个浮点数?
参考答案
- dict 键需要可哈希;不可变类型可哈希,list 可变故不可哈希。
- 会变;字符串拼接创建了新对象,名字 s 重新绑定到它。
math.isclose(a, b)或改用decimal.Decimal精确运算。
11. 与其他知识点的关系
12. 延伸阅读
- Python 官方文档 Built-in Types:https://docs.python.org/zh-cn/3/library/stdtypes.html
- Fluent Python 第 2 章