在我看来,python社区分为了三个流派,分别是python 2.x组织,3.x组织和PyPy组织。这个分类基本上可以归根于类库的兼容性和速度。这篇文章将聚焦于一些通用代码的优化技巧以及编译成C后性能的显著提升,当然我也会给出三大主要python流派运行时间。我的目的不是为了证明一个比另一个强,只是为了让你知道如何在不同的环境下使用这些具体例子作比较。
使用生成器
一个普遍被忽略的内存优化是生成器的使用。生成器让我们创建一个函数一次只返回一条记录,而不是一次返回所有的记录,如果你正在使用python2.x,这就是你为啥使用xrange替代range或者使用ifilter替代filter的原因。一个很好地例子就是创建一个很大的列表并将它们拼合在一起。
import timeitimport random def generate(num):while num:yield random.randrange(10)num -= 1 def create_list(num):numbers = []while num:numbers.append(random.randrange(10))num -= 1return numbersprint(timeit.timeit("sum(generate(999))", setup="from __main__ import generate", number=1000))>>> 0.88098192215 #Python 2.7>>> 1.416813850402832 #Python 3.2print(timeit.timeit("sum(create_list(999))", setup="from __main__ import create_list", number=1000))>>> 0.924163103104 #Python 2.7>>> 1.5026731491088867 #Python 3.2
这不仅是快了一点,也避免了你在内存中存储全部的列表!
Ctypes的介绍
对于关键性的性能代码python本身也提供给我们一个API来调用C方法,主要通过 ctypes来实现,你可以不写任何C代码来利用ctypes。默认情况下python提供了预编译的标准c库,我们再回到生成器的例子,看看使用ctypes实现花费多少时间。
import timeitfrom ctypes import cdll def generate_c(num):#Load standard C librarylibc = cdll.LoadLibrary("libc.so.6") #Linux#libc = cdll.msvcrt #Windowswhile num:yield libc.rand() % 10num -= 1 print(timeit.timeit("sum(generate_c(999))", setup="from __main__ import generate_c", number=1000))>>> 0.434374809265 #Python 2.7>>> 0.7084300518035889 #Python 3.2
仅仅换成了c的随机函数,运行时间减了大半!现在如果我告诉你我们还能做得更好,你信吗?
Cython的介绍
Cython 是python的一个超集,允许我们调用C函数以及声明变量来提高性能。尝试使用之前我们需要先安装Cython.
sudo pip install cython
Cython 本质上是另一个不再开发的类似类库Pyrex的分支,它将我们的类Python代码编译成C库,我们可以在一个python文件中调用。对于你的python文件使用.pyx后缀替代.py后缀,让我们看一下使用Cython如何来运行我们的生成器代码。
#cython_generator.pyximport random def generate(num):while num:yield random.randrange(10)num -= 1
新闻热点
疑难解答