其他优化技巧 分类: python 2013-01-22 11:05 178人阅读 评论(0) 收藏

其他优化技巧

1. 如果需要交换两个变量的值使用 a,b=b,a 而不是借助中间变量 t=a;a=b;b=t;

>>> from timeit import Timer

>>> Timer("t=a;a=b;b=t","a=1;b=2").timeit()

0.25154118749729365

>>> Timer("a,b=b,a","a=1;b=2").timeit()

0.17156677734181258

>>>

2. 在循环的时候使用 xrange 而不是 range;使用 xrange 可以节省大量的系统内存,因为 xrange() 在序列中每次调用只产生一个整数元素。而 range() 將直接返回完整的元素列表,用于循环时会有不必要的开销。在 python3 中 xrange 不再存在,里面 range 提供一个可以遍历任意长度的范围的 iterator。

3. 使用局部变量,避免"global" 关键字。python 访问局部变量会比全局变量要快得多,因此可以利用这一特性提升性能。

4. if done is not None 比语句 if done != None 更快,读者可以自行验证;

5. 在耗时较多的循环中,可以把函数的调用改为内联的方式;

6. 使用级联比较 "x < y < z" 而不是 "x < y and y < z";

7. while 1 要比 while True 更快(当然后者的可读性更好);

8. build in 函数通常较快,add(a,b) 要优于 a+b。

结论

这些不能替代大脑思考. 打开引擎盖充分了解是开发者的职责,使得他们不会快速拼凑出一个垃圾设计. 以上的Python建议可以帮助你获得好的性能. 如果速度还不够快, Python將需要借助外力:分析和运行外部代码。


使用工具监控代码 而不是直觉

速度的问题可能很微妙, 所以不要依赖于直觉. 感谢 "cprofiles" 模块, 通过简单的运行你就可以监控Python代码.

1. “python -m cProfile myprogram.py”

clip_image014

2. 使用import profile模块

import profile

def profileTest():

Total =1;

for i in range(10):

Total=Total*(i+1)

print Total

return Total

if __name__ == "__main__":

profile.run("profileTest()")

程序的运行结果如下:

clip_image016

其中输出每列的具体解释如下:

ncalls:表示函数调用的次数;

tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;

percall:(第一个 percall)等于 tottime/ncalls;

cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;

percall:(第二个 percall)即函数运行一次的平均时间,等于 cumtime/ncalls;

filename:lineno(function):每个函数调用的具体信息;

如果需要将输出以日志的形式保存,只需要在调用的时候加入另外一个参数。如 profile.run("profileTest()","testprof")。

对于大型应用程序,如果能够将性能分析的结果以图形的方式呈现,将会非常实用和直观,常见的可视化工具有 Gprof2Dot,visualpytune,KCacheGrind 等,读者可以自行查阅相关官网。

审查时间复杂度

控制以后, 提供一个基本的算法性能分析. 恒定时间是理想值. 对数时间复度是稳定的. 阶乘复杂度很难扩展.

O(1) -> O(lg n) -> O(n lg n) -> O(n^2) -> O(n^3) -> O(n^k) -> O(k^n) -> O(n!)

使用第三方包

Python 性能优化除了改进算法,选用合适的数据结构之外,还有几种关键的技术,比如将关键 python 代码部分重写成 C 扩展模块,或者选用在性能上更为优化的解释器等,这些在本文中统称为优化工具。python 有很多自带的优化工具,如 Psyco,Pypy,Cython,Pyrex 等,这些优化工具各有千秋。


posted @ 2013-01-22 11:05  前行者2011  阅读(114)  评论(0编辑  收藏  举报