算法与代码优化
问题
Python 代码层面有哪些常见的性能优化技巧?
答案
数据结构选择
| 操作 | list | set | dict |
|---|---|---|---|
| 查找 (in) | |||
| 追加 | |||
| 删除 |
# ❌ 在 list 中查找——O(n)
if item in large_list:
# ✅ 转为 set 查找——O(1)
large_set = set(large_list)
if item in large_set:
列表推导 vs 循环
import timeit
# ❌ 慢:for 循环 + append
def slow():
result = []
for i in range(10000):
result.append(i * 2)
return result
# ✅ 快:列表推导(C 层面循环)
def fast():
return [i * 2 for i in range(10000)]
# 快约 30%
生成器避免内存爆炸
# ❌ 创建完整列表占用大量内存
total = sum([x ** 2 for x in range(10_000_000)])
# ✅ 生成器表达式——逐个计算,几乎不占内存
total = sum(x ** 2 for x in range(10_000_000))
字符串拼接
# ❌ 慢:字符串拼接(每次创建新对象)
result = ""
for s in strings:
result += s
# ✅ 快:join(一次性分配内存)
result = "".join(strings)
批量操作
# ❌ 慢:逐条插入数据库
for user in users:
await session.execute(insert(User).values(**user))
# ✅ 快:批量插入
await session.execute(insert(User), users)
# ❌ 慢:逐个请求
for url in urls:
await client.get(url)
# ✅ 快:并发请求
await asyncio.gather(*[client.get(url) for url in urls])
内置函数优先
# ❌ 手写循环
total = 0
for x in data:
total += x
# ✅ 内置 sum(C 实现)
total = sum(data)
# 其他内置函数也是如此
max(data) # 比手写循环快
sorted(data) # 比手写排序快
any(...) # 短路求值
all(...)
常见面试问题
Q1: Python 为什么"慢"?怎么办?
答案:
- 动态类型:每次运算都要检查类型
- 解释执行:没有编译为机器码
- GIL:CPU 密集型无法并行
优化策略:
- 选对数据结构和算法(最重要)
- 用内置函数和 NumPy 向量化
- I/O 密集型用异步
- CPU 密集型用多进程或 Cython/Numba
Q2: 什么时候不该优化?
答案:
"过早优化是万恶之源" —— Donald Knuth
- 代码还没写对时不优化
- 没有性能问题时不优化
- 没有 Profile 数据时不优化
先保证正确性和可读性,有性能问题时用 Profile 找到瓶颈再针对性优化。