六个窍门助你提高Python运行效率


Posted in Python onJune 09, 2015

不喜欢Python的人经常会吐嘈Python运行太慢。但是,事实并非如此。尝试以下六个窍门,来为你的Python应用提速。

窍门一:关键代码使用外部功能包

Python简化了许多编程任务,但是对于一些时间敏感的任务,它的表现经常不尽人意。使用C/C++或机器语言的外部功能包处理时间敏感任务,可以有效提高应用的运行效率。这些功能包往往依附于特定的平台,因此你要根据自己所用的平台选择合适的功能包。简而言之,这个窍门要你牺牲应用的可移植性以换取只有通过对底层主机的直接编程才能获得的运行效率。以下是一些你可以选择用来提升效率的功能包:

Cython
Pylnlne
PyPy
Pyrex

这些功能包的用处各有不同。比如说,使用C语言的数据类型,可以使涉及内存操作的任务更高效或者更直观。Pyrex就能帮助Python延展出这样的功能。Pylnline能使你在Python应用中直接使用C代码。内联代码是独立编译的,但是它把所有编译文件都保存在某处,并能充分利用C语言提供的高效率。

窍门二:在排序时使用键

Python含有许多古老的排序规则,这些规则在你创建定制的排序方法时会占用很多时间,而这些排序方法运行时也会拖延程序实际的运行速度。最佳的排序方法其实是尽可能多地使用键和内置的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)],

在每段例子里,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版本是否足够高效来支持这一更新。

你要保证自己的代码在新版本里还能运行。你需要使用新的函数库才能体验新的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的版本下,有的窍门或许比其他的表现更好,但这有时候甚至取决于平台的差异。你需要总结分析你的应用,找到它效率低下的部分,然后尝试这些窍门,找到解决问题的最佳方法。

Python 相关文章推荐
python通过zlib实现压缩与解压字符串的方法
Nov 19 Python
Python实现二叉树结构与进行二叉树遍历的方法详解
May 24 Python
《Python学习手册》学习总结
Jan 17 Python
Python实现的生成格雷码功能示例
Jan 24 Python
Python正则表达式指南 推荐
Oct 09 Python
python的sorted用法详解
Jun 25 Python
django formset实现数据表的批量操作的示例代码
Dec 06 Python
Python3 把一个列表按指定数目分成多个列表的方式
Dec 25 Python
基于opencv实现简单画板功能
Aug 02 Python
Python 文本滚动播放器的实现代码
Apr 25 Python
python如何进行基准测试
Apr 26 Python
方法汇总:Python 安装第三方库常用
Apr 26 Python
python数组复制拷贝的实现方法
Jun 09 #Python
Python函数返回值实例分析
Jun 08 #Python
python下MySQLdb用法实例分析
Jun 08 #Python
Python赋值语句后逗号的作用分析
Jun 08 #Python
Python中逗号的三种作用实例分析
Jun 08 #Python
Python文件右键找不到IDLE打开项解决办法
Jun 08 #Python
Python判断字符串与大小写转换
Jun 08 #Python
You might like
PHP中for循环语句的几种变型
2006/11/26 PHP
php中删除数组的第一个元素和最后一个元素的函数
2015/03/07 PHP
php错误日志简单配置方法
2016/07/11 PHP
功能强大的php文件上传类
2016/08/29 PHP
PHP实现微信退款的方法示例
2019/03/26 PHP
href下载文件根据id取url并下载
2014/05/28 Javascript
jquery获取当前日期的方法
2015/01/14 Javascript
jquery插件corner实现圆角边框的方法
2015/03/09 Javascript
js 连续赋值的简单实现
2016/06/13 Javascript
Vue.js计算属性computed与watch(5)
2016/12/09 Javascript
利用JS制作万年历的方法
2017/08/16 Javascript
iframe与主框架跨域相互访问实现方法
2017/09/14 Javascript
基于JavaScript实现五子棋游戏
2020/08/26 Javascript
jQuery实现图片上传预览效果功能完整实例【测试可用】
2018/05/28 jQuery
Vue如何实现响应式系统
2018/07/11 Javascript
angular学习之动态创建表单的方法
2018/12/07 Javascript
微信小程序上传文件到阿里OSS教程
2019/05/20 Javascript
ES6 class的应用实例分析
2019/06/27 Javascript
解决vuecli3中img src 的引入问题
2020/08/04 Javascript
vue中的计算属性和侦听属性
2020/11/06 Javascript
微信小程序实现左滑删除效果
2020/11/18 Javascript
深度辨析Python的eval()与exec()的方法
2019/03/26 Python
python程序变成软件的实操方法
2019/06/24 Python
pycharm new project变成灰色的解决方法
2019/06/27 Python
PyTorch的SoftMax交叉熵损失和梯度用法
2020/01/15 Python
CSS Grid布局教程之浏览器开启CSS Grid Layout汇总
2014/12/30 HTML / CSS
什么是"引用"?申明和使用"引用"要注意哪些问题?
2016/03/03 面试题
WSDL的操作类型主要有几种
2013/07/19 面试题
数控专业推荐信范文
2013/12/02 职场文书
《雨霖铃》听课反思
2014/02/13 职场文书
军校大学生个人的自我评价
2014/02/17 职场文书
项目验收申请报告
2015/05/15 职场文书
2016年教师师德师风承诺书
2016/03/25 职场文书
如何才能写好调研报告?
2019/07/03 职场文书
2019年励志签名:致拼搏路上的自己
2019/10/11 职场文书
使用CSS实现小三角边框原理解析
2021/11/07 HTML / CSS