① Memory & Types
可变 vs 不可变
- 不可变:
int/str/tuple→ 可作 dict key - 可变:
list/dict/set→ 不能作 dict key
is vs ==
is→ 同一个对象;==→ 值相等a = [1,2]; b = [1,2]→a == b但a is not b
深/浅拷贝
- 浅拷贝
copy.copy():嵌套对象仍是引用 - 深拷贝
copy.deepcopy():完全独立的副本
⚠️ 经典陷阱:
def f(x=[])默认参数只创建一次,所有调用共享!
正确写法:def f(x=None): x = x or []
② Data Structures
| 类型 | 特点 |
|---|---|
list | 增删末尾 O(1),pop(0) / insert 是 O(n) |
dict | 查找/插入/删除 O(1),Python 3.7+ 有序 |
set | 成员判断 O(1),元素必须可哈希 |
tuple | 不可变 list,可作 dict key |
怎么选:
- 需要快速查找 →
dict/set - 需要头尾操作 →
collections.deque - 需要优先队列 →
heapq(最小堆) - 计数 →
Counter;自动默认值 →defaultdict
排序:sort() / sorted() 都是 Timsort,稳定,O(n log n)
③ Functions
装饰器
- 本质:
@dec≡func = dec(func),是语法糖 - 用途:日志、计时、权限校验、缓存
- ⚠️ 要用
@functools.wraps(func)保留原函数名
生成器
- 用
yield代替return,惰性求值,省内存 - 大数据优先用
(x for x in ...)而非[x for x in ...]
常用内置
map/filter/zip/enumeratelambda:匿名函数,适合简单场景*args(tuple)/**kwargs(dict):可变参数
④ OOP & Classes
三大特性:封装 / 继承 / 多态
常考区别:
@classmethod→ 第一个参数是cls,可访问类,常用于工厂方法@staticmethod→ 普通函数,放在类里只是归类,不能访问类或实例@property→ 把方法当属性用,可加 setter 做数据验证
继承与 MRO:
- 多继承时方法查找顺序:
ClassName.__mro__ - 用
super()调用父类方法
__str__ vs __repr__:
__str__→print()显示,给用户看__repr__→ 调试用,应能还原对象
⑤ GIL & Concurrency
GIL 是什么
CPython 的全局锁,同一时刻只有一个线程跑 Python 代码。
原因:内存管理(引用计数)不是线程安全的。
核心结论:
- I/O 密集(网络请求、文件读写)→ 用
threading - CPU 密集(大量计算)→ 用
multiprocessing
asyncio:
async/await 写法,单线程处理大量 I/O 并发,适合高并发网络场景。
⚠️ 不能有任何阻塞调用(否则会卡死整个事件循环)
⑥ Common Pitfalls
循环闭包
funcs = [lambda: i for i in range(3)]
print([f() for f in funcs]) # [2, 2, 2] ← 全是 2!
# 正确:
funcs = [lambda i=i: i for i in range(3)]字符串拼接
# 慢,O(n²)
s = ""
for word in words:
s += word
# 快
s = "".join(words)None 判断
if x is None: # ✅
if x == None: # ❌列表推导式 vs 循环
推导式在 C 层面执行,比等价的 for 循环快 30-50%,优先使用。
with 语句
上下文管理器,自动处理资源的释放(文件关闭、锁释放等)。