算法的时间复杂度对程序的执行效率影响最大,在Python中能够经过选择合适的数据结构来优化时间复杂度,如list和set查找某一个元素的时间复杂度分别是O(n)和O(1)。不一样的场景有不一样的优化方式,总得来讲,通常有分治,分支界限,贪心,动态规划等思想。java
如用上三角或下三角的方式去保存一个大的对称矩阵。在0元素占大多数的矩阵里使用稀疏矩阵表示。python
对于dict和list等数据结构的对象,直接赋值使用的是引用的方式。而有些状况下须要复制整个对象,这时可使用copy包里的copy和deepcopy,这两个函数的不一样之处在于后者是递归复制的。效率也不同:(如下程序在ipython中运行)c++
timeit后面的-n表示运行的次数,后两行对应的是两个timeit的输出,下同。因而可知后者慢一个数量级。算法
python dict和set都是使用hash表来实现(相似c++11标准库中unordered_map),查找元素的时间复杂度是O(1)编程
dict的效率略高(占用的空间也多一些)。json
使用()获得的是一个generator对象,所须要的内存空间与列表的大小无关,因此效率会高一些。在具体应用上,好比set(i for i in range(100000))会比set([i for i in range(100000)])快。数据结构
可是对于须要循环遍历的状况:多线程
后者的效率反而更高,可是若是循环里有break,用generator的好处是显而易见的。yield也是用于建立generator:app
对于内存不是很是大的list,能够直接返回一个list,可是可读性yield更佳(人个喜爱)。分布式
python2.x内置generator功能的有xrange函数、itertools包等。
循环以外能作的事不要放在循环内,好比下面的优化能够快一倍:
对于and,应该把知足条件少的放在前面,对于or,把知足条件多的放在前面。如:
join对于累加的方式,有大约5倍的提高。
三种状况中,%的方式是最慢的,可是三者的差距并不大(都很是快)。(我的以为%的可读性最好)
使用a,b=b,a而不是c=a;a=b;b=c;来交换a,b的值,能够快1倍以上。
使用 if is True 比 if == True 将近快一倍。
x < y < z效率略高,并且可读性更好。
while 1 比 while true快不少,缘由是在python2.x中,True是一个全局变量,而非关键字。
**就是快10倍以上!
由c实现的包,速度快10倍以上!
下面比较了eval, cPickle, json方式三种对相应字符串反序列化的效率:
可见json比cPickle快近3倍,比eval快20多倍。
目前主要有CPython(python最多见的实现的方式)原生API, ctypes,Cython,cffi三种方式,它们的做用是使得Python程序能够调用由C编译成的动态连接库,其特色分别是:
CPython原生API: 经过引入Python.h头文件,对应的C程序中能够直接使用Python的数据结构。实现过程相对繁琐,可是有比较大的适用范围。
ctypes: 一般用于封装(wrap)C程序,让纯Python程序调用动态连接库(Windows中的dll或Unix中的so文件)中的函数。若是想要在python中使用已经有C类库,使用ctypes是很好的选择,有一些基准测试下,python2+ctypes是性能最好的方式。
Cython: Cython是CPython的超集,用于简化编写C扩展的过程。Cython的优势是语法简洁,能够很好地兼容numpy等包含大量C扩展的库。Cython的使得场景通常是针对项目中某个算法或过程的优化。在某些测试中,能够有几百倍的性能提高。
cffi: cffi的就是ctypes在pypy(详见下文)中的实现,同进也兼容CPython。cffi提供了在python使用C类库的方式,能够直接在python代码中编写C代码,同时支持连接到已有的C类库。
使用这些优化方式通常是针对已有项目性能瓶颈模块的优化,能够在少许改动原有项目的状况下大幅度地提升整个程序的运行效率。
由于GIL的存在,Python很难充分利用多核CPU的优点。可是,能够经过内置的模块multiprocessing实现下面几种并行模式:
多进程:对于CPU密集型的程序,可使用multiprocessing的Process,Pool等封装好的类,经过多进程的方式实现并行计算。可是由于进程中的通讯成本比较大,对于进程之间须要大量数据交互的程序效率未必有大的提升。
多线程:对于IO密集型的程序,multiprocessing.dummy模块使用multiprocessing的接口封装threading,使得多线程编程也变得很是轻松(好比可使用Pool的map接口,简洁高效)。
分布式:multiprocessing中的Managers类提供了能够在不一样进程之共享数据的方式,能够在此基础上开发出分布式的程序。
不一样的业务场景能够选择其中的一种或几种的组合实现程序性能的优化。
PyPy是用RPython(CPython的子集)实现的Python,根据官网的基准测试数据,它比CPython实现的Python要快6倍以上。快的缘由是使用了Just-in-Time(JIT)编译器,即动态编译器,与静态编译器(如gcc,javac等)不一样,它是利用程序运行的过程的数据进行优化。因为历史缘由,目前pypy中还保留着GIL,不过正在进行的STM项目试图将PyPy变成没有GIL的Python。
若是python程序中含有C扩展(非cffi的方式),JIT的优化效果会大打折扣,甚至比CPython慢(比Numpy)。因此在PyPy中最好用纯Python或使用cffi扩展。
随着STM,Numpy等项目的完善,相信PyPy将会替代CPython。
除了上面在ipython使用到的timeit模块,还有cProfile。cProfile的使用方式也很是简单: python -m cProfile filename.py,filename.py 是要运行程序的文件名,能够在标准输出中看到每个函数被调用的次数和运行的时间,从而找到程序的性能瓶颈,而后能够有针对性地优化。