提升Python程序运行效率的6个方法


Posted in Python onMarch 31, 2015

Python是一个很酷的语言,因为你可以在很短的时间内利用很少的代码做很多事情。不仅如此,它还能轻松地支持多任务,比如多进程等。Python批评者有时会说Python执行缓慢。本文将尝试介绍6个技巧,可加速你的Python应用程序。
1.让关键代码依赖于外部包

虽然Python让许多编程任务变得容易,但它可能并不总能为紧急的任务提供最佳性能。你可以为紧急的任务使用C、C++或机器语言编写的外部包,这样可以提高应用程序的性能。这些包都是不能跨平台的,这意味着你需要根据你正在使用的平台,寻找合适的包。简而言之,这个方案放弃了一些应用程序的可移植性,以换取只有在特定主机上直接编程才能获得的程序性能。这里有一些你应该考虑加入到你的“性能兵工厂”的包:

  •     Cython
  •    PyInlne
  •     PyPy
  •     Pyrex

这些包以不同的方式提高性能。例如,Pyrex能够扩展Python所能做的事情,例如使用C的数据类型来让内存任务更加有效或直接。PyInIne让你在Python应用程序中直接使用C代码。程序中的内联代码单独编译,但它在利用C语言所能提供的效率的同时,也让所有的代码都在同一个地方。
2.排序时使用键(key)

有很多老的Python排序代码,它们在你创建一个自定义的排序时花费你的时间,但在运行时确实能加速执行排序过程。元素排序的最好方法是尽可能使用键(key)和默认的sort()排序方法。例如,考虑下面的代码:

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)],

每一个实例中,根据你选择的作为key参数部分的索引,数组进行了排序。类似于利用数字进行排序,这种方法同样适用于利用字符串排序。
3.优化循环

每种编程语言都会强调需要优化循环。当使用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原生的解释器在那种情况下,真的会减缓执行的速度。

(注意:优化循环的方法有很多,这只是其中的一个。例如,许多程序员都会说,列表推导是在循环中提高执行速度的最好方式。这里的关键是,优化循环是程序取得更高的执行速度的更好方式之一。)
4.使用较新版本的Python

在网上搜索Python信息,都会发现无数人在问,从Python一个版本迁移到另一个版本的问题的信息。一般来说,Python的每一个版本都包含了能让其比上个版本运行更快的优化。版本迁移的限制因素是,你喜欢的那些库是否已经迁移到Python的较新版本。相比于询问是否应该进行版本迁移,关键问题是确定一个新版本什么时候有足够的支持,以保证迁移的可行性。

你需要验证你的代码仍然运行。你需要在Python的新版本下使用你获得的新库,然后检查你的应用程序是否需要重大改变。只有在你作出必要的更正之后,你才会注意到版本之间的差别。然而,如果你正好确保你的应用程序能在新版本下运行,而不需要任何改变,你可能会错过那些版本升级带来的新特性。一旦你进行了迁移,你应该为你的新版本下的应用程序写一个说明,检查有问题的地方,并且优先考虑利用新版本的特性去更新那些地方。这样用户将会在升级的过程中更早的看到一个更大的性能提升。
5.尝试多种编码方法

如果每次你创建一个应用程序都是用相同的编码方法,几乎肯定会导致一些你的应用程序比它能够达到的运行效率慢的情况。作为分析过程的一部分,你可以尝试一些实验。例如,在一个字典中管理一些元素,你可以采用安全的方法确定元素是否已经存在并更新,或者你可以直接添加元素,然后作为异常处理该元素不存在情况。考虑第一个编码的例子:

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)

两种情况下具有相同的输出:{‘d': 4, ‘c': 4, ‘b': 4, ‘a': 4}。唯一的不同是这个输出是如何得到的。跳出固定的思维模式,创造新的编码技巧,能够帮助你利用你的应用程序获得更快的结果。
6.交叉编译应用程序

开发者有时会忘记,电脑实际上是不懂任何用于创建现代应用程序的语言,电脑所能懂得是机器代码。为了能在电脑上运行应用程序,你使用一个应用将人类可读的代码你转换成计算机能理解的。有时候用一种语言,比如Python,写一个应用,并用另一种语言,比如C++,运行它,从性能的角度来看是有意义的。这取决于你想要应用程序去做什么,以及主机系统可以提供的资源。

一个有趣的交叉编译器,Nuitka,可以将你的Python代码转换为C++代码。这么做的结果是,你可以在原生模式下执行应用程序,而不是依靠解释器。根据平台和任务,你可以看到一个显著的性能提升。

(注意:Nuitka目前还处于测试阶段,所以用它来产品程序时需要小心。实际上,目前最好将其用于实验。现在也有一些关于交叉编译是否是得到更好性能的最佳方式的讨论。开发者已经利用交叉编译好几年了,目的是实现特定的目标,比如更好的应用程序的速度。记住,每一个解决方案都会有得有失,你应该在将一个解决方案用于生产环境之前就好好考虑一下得失情况。)

在使用一个交叉编译器时,要确保它支持你使用的Python的版本。Nuitka支持Python2.6、2.7、3.2和3.3。想让这个方案发挥作用,你需要一个Python解释器和一个C++编译器。Nuitka支持多种C++编译器,包括Microsoft Visual Studio、MinGW 和 Clang/LLVM。

交叉编译也可能带来一些严重的负面影响。例如,当利用Nuitka工作时,你会发现即使一个小程序也能消耗很大的硬盘空间,这是因为Nuitka使用大量的动态链接库(DLLs)实现Python的功能。所以当你面对一个资源有限的系统时,这个方案可能不会很好的起作用。
总结

这六个技巧中的任意一个,都可以帮助你创造更快的Python程序。但任何技巧都不是万能的,不能每次都起作用。有些技巧在Python的特定版本下比其他技巧的更有效——甚至系统平台也能影响它们的效果。你需要配置你的应用,确定哪个地方让其运行缓慢,然后尝试似乎能最好的解决这些问题的一些技巧。

Python 相关文章推荐
python list排序的两种方法及实例讲解
Mar 20 Python
Python实现将json文件中向量写入Excel的方法
Mar 26 Python
Python爬虫实战:分析《战狼2》豆瓣影评
Mar 26 Python
如何使用 Pylint 来规范 Python 代码风格(来自IBM)
Apr 06 Python
python模块smtplib实现纯文本邮件发送功能
May 22 Python
python遍历文件夹,指定遍历深度与忽略目录的方法
Jul 11 Python
python的pstuil模块使用方法总结
Jul 26 Python
pytorch实现用CNN和LSTM对文本进行分类方式
Jan 08 Python
利用matplotlib为图片上添加触发事件进行交互
Apr 23 Python
使用Keras训练好的.h5模型来测试一个实例
Jul 06 Python
利用python如何实现猫捉老鼠小游戏
Dec 04 Python
总结三种用 Python 作为小程序后端的方式
May 02 Python
用Python从零实现贝叶斯分类器的机器学习的教程
Mar 31 #Python
利用Python的Flask框架来构建一个简单的数字商品支付解决方案
Mar 31 #Python
用Python进行基础的函数式编程的教程
Mar 31 #Python
python使用多线程不断刷新网页的方法
Mar 31 #Python
Python新手实现2048小游戏
Mar 31 #Python
举例介绍Python中的25个隐藏特性
Mar 30 #Python
在Python的循环体中使用else语句的方法
Mar 30 #Python
You might like
用PHP制作静态网站的模板框架(二)
2006/10/09 PHP
教你如何开启shopnc b2b2c 伪静态
2014/10/21 PHP
php中addslashes函数与sql防注入
2014/11/17 PHP
fsockopen pfsockopen函数被禁用,SMTP发送邮件不正常的解决方法
2015/09/20 PHP
PHP微信开发用Cache 解决数据缓存
2016/07/11 PHP
PHP依赖注入(DI)和控制反转(IoC)详解
2017/06/12 PHP
PHP自定义错误处理的方法分析
2018/12/19 PHP
PHP实现Snowflake生成分布式唯一ID的方法示例
2020/08/30 PHP
扩展String功能方法
2006/09/22 Javascript
firefox插件Firebug的使用教程
2010/01/02 Javascript
jQuery contains过滤器实现精确匹配使用方法
2013/04/12 Javascript
基于jquery插件实现拖拽删除图片功能
2020/08/27 Javascript
在html中引入外部js文件,并调用带参函数的方法
2016/10/31 Javascript
vue.js初学入门教程(1)
2016/11/03 Javascript
three.js加载obj模型的实例代码
2017/11/10 Javascript
vue.js中引入vuex储存接口数据及调用的详细流程
2017/12/14 Javascript
Vue 3.0双向绑定原理的实现方法
2019/10/23 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
[03:10]2014DOTA2 TI马来劲旅Titan首战告捷目标只是8强
2014/07/10 DOTA
python实现搜索指定目录下文件及文件内搜索指定关键词的方法
2015/06/28 Python
Python标准库笔记struct模块的使用
2018/02/22 Python
Python基于递归算法求最小公倍数和最大公约数示例
2018/07/27 Python
浅谈Python 多进程默认不能共享全局变量的问题
2019/01/11 Python
python实现字符串加密成纯数字
2019/03/19 Python
Python正则表达式急速入门(小结)
2019/12/16 Python
size?德国官方网站:英国伦敦的球鞋精品店
2018/03/17 全球购物
德国购买门票网站:ADticket.de
2019/10/31 全球购物
bonprix荷兰网上商店:便宜的服装、鞋子和家居用品
2020/07/04 全球购物
2014年党员整改措施
2014/10/24 职场文书
2014年环卫工作总结
2014/11/22 职场文书
安全保证书怎么写
2015/02/28 职场文书
《浅水洼里的小鱼》教学反思
2016/02/16 职场文书
python Polars库的使用简介
2021/04/21 Python
Python基础之tkinter图形化界面学习
2021/04/29 Python
pyqt5蒙版遮罩mask,setmask的使用
2021/06/11 Python
python字符串的一些常见实用操作
2022/04/06 Python