1. 数据类型
| 类型 | 说明 | 语法 |
|---|
NoneType | 空值 | None |
int | 整型 | 5, -10 |
float | 浮点型 | 3.14, -0.5 |
str | 字符串(不可变) | "world", 'hello' |
bool | 布尔 | True, False |
list | 有序、可变 | [1, 1, 3] |
tuple | 有序、不可变 | (1, 1, 3) |
set | 无序、唯一元素 | {1, 2, 3} |
dict | 键值对 | {'name': 'hex'} |
2. 列表与元组的区别
| 列表(list) | 元组(tuple) |
|---|
| 可变性 | 可增删改 | 不可变 |
| 语法 | [] | () |
| 方法 | append/remove/pop 等 | 仅 count/index |
| 内存 | 更大(预留扩容空间) | 更小 |
| 可作为 dict key | 不可以 | 可以 |
使用场景:需要动态修改用列表,固定的集合(如函数返回多个值、配置常量)用元组。元组可哈希,可作字典键。
3. GIL 与线程安全
CPython 的 GIL(Global Interpreter Lock)只保证单条字节码的原子性,不保证复合操作的安全性。
| 操作 | 线程安全? | 原因 |
|---|
x = 1 | 是 | 单条字节码 |
x += 1 | 否 | 多条字节码:LOAD + ADD + STORE,线程可能在任意点切换 |
list.append(1) | 是 | CPython 中 append 是原子操作 |
list[0] += 1 | 否 | 读 + 加法 + 写,可分片执行 |
依赖 GIL 来做线程安全是错误的方式。需要线程安全时使用:
threading.Lock:互斥锁queue.Queue:线程安全队列collections.deque:线程安全双端队列
4. 可变对象作为默认参数
1
2
3
4
5
6
| def add_item(item, target=[]): # 陷阱
target.append(item)
return target
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] ← 预期是 [2]
|
默认参数 [] 在函数定义时只创建一次,多次调用共享同一个列表对象。
正确写法:
1
2
3
4
5
| def add_item(item, target=None):
if target is None:
target = []
target.append(item)
return target
|
5. 浅拷贝与深拷贝
1
2
3
4
5
6
7
8
9
| import copy
a = [[1, 2], [3, 4]]
b = a[:] # 浅拷贝:外层容器复制,内部元素共享
c = copy.deepcopy(a) # 深拷贝:递归复制所有对象
a[0].append(99)
print(b[0]) # [1, 2, 99] ← 受到了影响
print(c[0]) # [1, 2] ← 不受影响
|
| 浅拷贝 | 深拷贝 |
|---|
| 外层容器 | 复制 | 复制 |
| 内层对象 | 共享引用 | 递归复制 |
[:] / list.copy() | 是 | — |
copy.copy() | 是 | — |
copy.deepcopy() | — | 是 |