六个窍门助你提高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 相关文章推荐
wxpython 学习笔记 第一天
Feb 09 Python
使用python将mdb数据库文件导入postgresql数据库示例
Feb 17 Python
python操作日期和时间的方法
Mar 11 Python
python解决网站的反爬虫策略总结
Oct 26 Python
详解python之配置日志的几种方式
May 22 Python
Python实现获取磁盘剩余空间的2种方法
Jun 07 Python
Python实现的删除重复文件或图片功能示例【去重】
Apr 23 Python
使用python来调用CAN通讯的DLL实现方法
Jul 03 Python
Python 限定函数参数的类型及默认值方式
Dec 24 Python
浅谈Python3实现两个矩形的交并比(IoU)
Jan 18 Python
pyqt5数据库使用详细教程(打包解决方案)
Mar 25 Python
Python如何使用PIL Image制作GIF图片
May 16 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 is_executable判断给定文件名是否可执行实例
2016/09/26 PHP
PHP convert_uudecode()函数讲解
2019/02/14 PHP
基于PHP+mysql实现新闻发布系统的开发
2020/08/06 PHP
JQuery 选项卡效果(JS与HTML的分离)
2010/04/01 Javascript
删除节点的jquery代码
2014/01/13 Javascript
jQuery使用slideUp方法实现控制元素缓慢收起
2015/03/27 Javascript
js实现简单的联动菜单效果
2015/08/19 Javascript
基于Node.js的强大爬虫 能直接发布抓取的文章哦
2016/01/10 Javascript
Vue.js自定义指令的用法与实例解析
2017/01/18 Javascript
使用node.js搭建服务器
2017/05/20 Javascript
Layui点击图片弹框预览的实现方法
2019/09/16 Javascript
Node.JS如何实现JWT原理
2020/09/18 Javascript
[01:46]TI4西雅图DOTA2前线报道 中国选手抱团调时差
2014/07/08 DOTA
[50:50]完美世界DOTA2联赛PWL S3 INK ICE vs DLG 第一场 12.20
2020/12/23 DOTA
python插入排序算法的实现代码
2013/11/21 Python
python中的编码知识整理汇总
2016/01/26 Python
基于python脚本实现软件的注册功能(机器码+注册码机制)
2016/10/09 Python
centos6.4下python3.6.1安装教程
2017/07/21 Python
Odoo中如何生成唯一不重复的序列号详解
2018/02/10 Python
python smtplib发送带附件邮件小程序
2018/05/22 Python
符合语言习惯的 Python 优雅编程技巧【推荐】
2018/09/25 Python
python-opencv获取二值图像轮廓及中心点坐标的代码
2019/08/27 Python
Python hashlib模块实例使用详解
2019/12/24 Python
详解tensorflow之过拟合问题实战
2020/11/01 Python
Pycharm安装Qt Design快捷工具的详细教程
2020/11/18 Python
澳大利亚领先的宠物用品商店:VetSupply
2017/09/08 全球购物
印度在线购物网站:Paytmmall
2019/07/24 全球购物
电气工程及其自动化学生实习自我鉴定
2013/09/19 职场文书
工艺工程师工作职责
2013/11/23 职场文书
技术股份合作协议书
2014/10/05 职场文书
父亲婚礼答谢词
2015/01/04 职场文书
恰同学少年观后感
2015/06/08 职场文书
2016新年感言
2015/08/03 职场文书
煤矿安全学习心得体会
2016/01/18 职场文书
Python的flask接收前台的ajax的post数据和get数据的方法
2021/04/12 Python
解决MySQL报“too many connections“错误
2022/04/19 MySQL