如何优化Python代码的性能?
说真的,别一上来就想着加啥多线程多进程,先看看你代码到底慢哪了。你光凭感觉搞优化,那不是“玄学调优”吗?我之前也犯过类似错误,手写一堆for循环,跑半天,最后发现是I/O操作拖的后腿,白折腾一晚上。你用time模块随便包一层:
import time
start = time.time()
# 你的代码段
end = time.time()
print('耗时:', end - start)
就这样,先知道自己慢在哪,别着急往多核分布式那方向冲。要是业务逻辑本身就写得臃肿,优化个寂寞。
别再手搓循环了,用内置函数
我特别受不了,有些人动不动就写好几层for循环,map、filter、list comprehension不用白不用啊!前几天在地铁上跟人扯淡,他说自己的数据处理慢得一批,我一看,原来是写了个三层嵌套的循环,真服气。你看这样:
# 慢得要死的传统写法
result = []
for i in range(1000000):
result.append(i * 2)
# 优雅又快的写法
result = [i * 2for i in range(1000000)]
不信你测一下,两者能差一倍以上。map、filter这些底层都是C写的,比你人肉for快多了。
少用全局变量、尽量用局部变量
这个真是血泪教训,我印象特别深。前两天组内CodeReview,有人写个函数里面全是global,调用堆全局变量,结果函数调用一多,性能直线下降。Python函数查找变量,先查局部,再查全局,局部快多了。所以你变量能放在局部,就别放全局。
尽量用生成器
这个也是,尤其是处理大数据量的时候,yield用起来是真的香。你要是还老想着用个list先全存下来,那内存分分钟爆掉。举个例子:
defread_big_file(file_path):
with open(file_path) as f:
for line in f:
yield line
for line in read_big_file('log.txt'):
# 处理每一行
pass
这样一行行来,内存用多少拿多少,贼省事。之前有次日志文件二十几个G,要不是用生成器,我电脑直接卡死。
真的慢到忍不了,再考虑多进程多线程
你真要用并发?先看清楚自己CPU是不是能带得动,I/O型的任务用多线程,CPU密集型任务多进程。Python有个GIL,单线程CPU任务根本提速不了。上次我帮小王改个爬虫,他写了多线程结果没提速,我说你用多进程,才发现刷刷往上涨。随便来个例子:
from concurrent.futures import ProcessPoolExecutor
defcpu_task(x):
return x ** 2
with ProcessPoolExecutor() as executor:
results = list(executor.map(cpu_task, range(10)))
print(results)
不过,多进程用多了,内存也会飞,别瞎加。
第三方库一定要用对
老实说,NumPy/Pandas这些库,用得熟,才是真的快。你还在for循环做矩阵运算,人家用NumPy一行就能干完还巨快。比如:
import numpy as np
a = np.arange(1000000)
b = a * 2
和你用for循环效率不是一个量级。再说Pandas,处理表格数据直接vectorized操作,效率刷刷的。
内存问题也别忽视
有时候你觉得自己优化得够快了,结果一堆对象没释放,内存耗完直接崩溃。要是用完变量记得del一下,或者局部作用域外面别留垃圾。大对象、临时变量啥的,用完早点丢,别拖累你后面代码。
cProfile先撸一遍
真要调优,上来先整cProfile看哪里最慢。python -m cProfile your_script.py,一跑全知道哪里拉胯。我之前有次查一个接口慢到要死,cProfile一看,是个正则写得太复杂,后来一改,提速80%。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领