跳到主要内容

算法与代码优化

问题

Python 代码层面有哪些常见的性能优化技巧?

答案

数据结构选择

操作listsetdict
查找 (in)O(n)O(n)O(1)O(1)O(1)O(1)
追加O(1)O(1)O(1)O(1)O(1)O(1)
删除O(n)O(n)O(1)O(1)O(1)O(1)
# ❌ 在 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 为什么"慢"?怎么办?

答案

  1. 动态类型:每次运算都要检查类型
  2. 解释执行:没有编译为机器码
  3. GIL:CPU 密集型无法并行

优化策略:

  • 选对数据结构和算法(最重要)
  • 用内置函数和 NumPy 向量化
  • I/O 密集型用异步
  • CPU 密集型用多进程或 Cython/Numba

Q2: 什么时候不该优化?

答案

"过早优化是万恶之源" —— Donald Knuth

  1. 代码还没写对时不优化
  2. 没有性能问题时不优化
  3. 没有 Profile 数据时不优化

先保证正确性和可读性,有性能问题时用 Profile 找到瓶颈再针对性优化。

相关链接