Python 是一门优秀的语言,它能让你在短期内经过极少许代码就能完成许多操做。不只如此,它还轻松支持多任务处理,好比多进程。程序员
不喜欢 Python 的人常常会吐嘈 Python 运行太慢。可是,事实并不是如此。尝试如下六个窍门,来为你的 Python 应用提速。编程
Python 简化了许多编程任务,可是对于一些时间敏感的任务,它的表现常常不尽人意。使用 C/C++ 或机器语言的外部功能包处理时间敏感任务,能够有效提升应用的运行效率。这些功能包每每依附于特定的平台,所以你要根据本身所用的平台选择合适的功能包。简而言之,这个窍门要你牺牲应用的可移植性以换取只有经过对底层主机的直接编程才能得到的运行效率。如下是一些你能够选择用来提高效率的功能包:小程序
- Cython
- Pylnlne
- PyPy
- Pyrex
这些功能包的用处各有不一样。好比说,使用C语言的数据类型,可使涉及内存操做的任务更高效或者更直观。Pyrex 就能帮助 Python 延展出这样的功能。Pylnline 能使你在Python 应用中直接使用 C 代码。内联代码是独立编译的,可是它把全部编译文件都保存在某处,并能充分利用 C 语言提供的高效率。安全
Python 含有许多古老的排序规则,这些规则在你建立定制的排序方法时会占用不少时间,而这些排序方法运行时也会拖延程序实际的运行速度。最佳的排序方法实际上是尽量多地使用键和内置的 sort() 方法。譬如,拿下面的代码来讲:app
import operator somelist = [(1, 5, 8), (6, 2, 4), (9, 7, 5)] somelist.sort(key=operator.itemgetter(0)) somelist #Output = [(1, 5, 8), (6, 2, 4), (9, 7, 5)] somelist.sort(key=operator.itemgetter(1)) somelist #Output = [(6, 2, 4), (1, 5, 8), (9, 7, 5)] somelist.sort(key=operator.itemgetter(2)) somelist #Output = [(6, 2, 4), (9, 7, 5), (1, 5, 8)],
在每段例子里,list 都是根据你选择的用做关键参数的索引进行排序的。这个方法不只对数值类型有效,还一样适用于字符串类型。编程语言
每一种编程语言都强调最优化的循环方案。当使用 Python 时,你能够借助丰富的技巧让循环程序跑得更快。然而,开发者们常常遗忘的一个技巧是:尽可能避免在循环中访问变量的属性。譬如,拿下面的代码来讲:函数
lowerlist = ['this', 'is', 'lowercase'] upper = str.upper upperlist = [] append = upperlist.append for word in lowerlist: append(upper(word)) print(upperlist) #Output = ['THIS', 'IS', 'LOWERCASE']
每次你调用 str.upper, Python 都会计算这个式子的值。然而,若是你把这个求值赋值给一个变量,那么求值的结果就能提早知道,Python 程序就能运行得更快。所以,关键就是尽量减少Python在循环中的工做量。由于 Python 解释执行的特性,在上面的例子中会大大减慢它的速度。性能
(注意:优化循环的方法还有不少,这只是其中之一。好比,不少程序员会认为,列表推导式是提升循环速度的最佳方法。关键在于,优化循环方案是提升应用程序运行速度的上佳选择。)测试
若是你在网上搜索 Python,你会发现数不尽的信息都是关于如何升级 Python 版本。一般,每一个版本的 Python 都会包含优化内容,使其运行速度优于以前的版本。可是,限制因素在于,你最喜欢的函数库有没有同步更新支持新的 Python 版本。与其争论函数库是否应该更新,关键在于新的 Python 版本是否足够高效来支持这一更新。优化
你要保证本身的代码在新版本里还能运行。你须要使用新的函数库才能体验新的 Python 版本,而后你须要在作出关键性的改动时检查本身的应用。只有当你完成必要的修正以后,你才能体会新版本的不一样。
然而,若是你只是确保本身的应用在新版本中能够运行,你极可能会错过新版本提供的新特性。一旦你决定更新,请分析你的应用在新版本下的表现,并检查可能出问题的部分,而后优先针对这些部分应用新版本的特性。只有这样,用户才能在更新之初就觉察到应用性能的改观。
每次建立应用时都使用同一种编码方法几乎无一例外会致使应用的运行效率不尽人意。能够在程序分析时尝试一些试验性的办法。譬如说,在处理字典中的数据项时,你既可使用安全的方法,先确保数据项已经存在再进行更新,也能够直接对数据项进行更新,把不存在的数据项做为特例分开处理。请看下面第一段代码:
n = 16 myDict = {} for i in range(0, n): char = 'abcd'[i%4] if char not in myDict: myDict[char] = 0 myDict[char] += 1 print(myDict)
当一开始 myDict 为空时,这段代码会跑得比较快。然而,一般状况下,myDict 填满了数据,至少填有大部分数据,这时换另外一种方法会更有效率。
n = 16 myDict = {} for i in range(0, n): char = 'abcd'[i%4] try: myDict[char] += 1 except KeyError: myDict[char] = 1 print(myDict)
在两种方法中输出结果都是同样的。区别在于输出是如何得到的。跳出常规的思惟模式,建立新的编程技巧能使你的应用更有效率。
开发者有时会忘记计算机其实并不理解用来建立现代应用程序的编程语言。计算机理解的是机器语言。为了运行你的应用,你借助一个应用将你所编的人类可读的代码转换成机器可读的代码。有时,你用一种诸如 Python 这样的语言编写应用,再以 C++ 这样的语言运行你的应用,这在运行的角度来讲,是可行的。关键在于,你想你的应用完成什么事情,而你的主机系统能提供什么样的资源。
Nuitka
是一款有趣的交叉编译器,能将你的 Python 代码转化成 C++ 代码。这样,你就能够在 native 模式下执行本身的应用,而无需依赖于解释器程序。你会发现本身的应用运行效率有了较大的提升,可是这会因平台和任务的差别而有所不一样。
(注意:Nuitka
如今还处在测试阶段,因此在实际应用中请多加注意。实际上,当下最好仍是把它用于实验。此外,关于交叉编译是否为提升运行效率的最佳方法还存在讨论的空间。开发者已经使用交叉编译多年,用来提升应用的速度。记住,每一种解决办法都有利有弊,在把它用于生产环境以前请仔细权衡。)
在使用交叉编译器时,记得确保它支持你所用的 Python 版本。Nuitka 支持Python2.6, 2.7, 3.2和3.3。为了让解决方案生效,你须要一个 Python 解释器和一个C++编译器。Nuitka 支持许多 C++ 编译器,其中包括Microsoft Visual Studio
,MinGW
和 Clang/LLVM
。
交叉编译可能形成一些严重问题。好比,在使用 Nuitka 时,你会发现即使是一个小程序也会消耗巨大的驱动空间。由于 Nuitka 借助一系列的动态连接库(DDLs)来执行Python 的功能。所以,若是你用的是一个资源颇有限的系统,这种方法或许不太可行。
结论
前文所述的六个窍门都能帮助你建立运行更有效率的Python应用。可是银弹是不存在的。上述的这些窍门不必定每次都能奏效。在特定的Python的版本下,有的窍门或许比其余的表现更好,但这有时候甚至取决于平台的差别。你须要总结分析你的应用,找到它效率低下的部分,而后尝试这些窍门,找到解决问题的最佳方法。