原文来自Python实用书:10种让Python超快的方法大多数人使用python是因为它很方便,而不是因为它快。过多的第三方库使得python与Java、C相比存在较大的性能差距。不过这也是可以理解的,因为在大多数情况下,开发速度优先于执行速度。但是也不要太担心python的速度,它不一定是非此即彼的命题。经过适当优化,Python应用程序可以以惊人的速度运行——可能不如Java或C快,但对于Web应用程序、数据分析、管理和自动化工具以及大多数其他用途来说已经足够快了。如此之快,您可能会忘记您是在用应用程序性能换取开发人员的工作效率。优化Python性能不能从单一的角度来看。相反,应用所有可用的优化方法,并选择最适合当前场景的一组多种方法。(Dropbox的人有一个最令人瞠目结舌的例子,展示了python优化的强大功能,点击链接查看。)在本文中,我将简要介绍许多常见的python优化方法。有些是临时措施,只需要将一种方法转换为另一种方法(例如更改Python解释器),但那些带来最大好处的方法需要更详细的工作。1.数数速度,数数速度,数数速度!如果你不能弄清楚为什么它很慢,你就不能确定为什么你的python应用程序没有像它应该的那样执行。计算方法有很多种。可以尝试使用python自带的cProfile模块进行简单的计算分析。如果需要更高的精度(计算每条语句的运行时间),可以使用第三方工具line_profiler。一般来说,分析计算程序的函数运行时间可以给你提供改进方案,所以推荐使用profilehooks第三方库,可以计算单个函数的运行时间。您可能需要更多的挖掘才能发现为什么您的程序在某处如此缓慢以及如何修复它。重点是缩小你调查的范围,逐渐细化到某种说法。2.缓存需要复用的数据。当你可以保存需要计算的数据时,不要重复计算它数千次。如果您有一个经常使用并返回可预测结果的函数,Python已经为您提供了将其缓存在内存中的选项。后续函数调用如果相同则立即返回结果。实现方式有很多种,例如:使用一个原生的python库:functools,有一个装饰器叫@functools.lru_cache,可以缓存函数最近的N次调用,当缓存的值保存一定时间后time这个在常量的时候很有用,比如列出最后一天用过的物品。3.将数学计算重构到NumPy如果你的Python程序中有基于矩阵或数组的数学运算,并且想更有效地对它们执行计算,那么你应该使用NumPy,因为它通过使用C库来完成繁重的工作它可以处理数组比本机python解释器更快,并且可以比Python的内置数据结构更有效地存储数字数据。NumPy还可以大大加快相对普通的数学运算。这个包提供了许多常见的Python数学运算的替代品,例如min和max,它们比原始Python快很多倍。NumPy的另一个优点是它可以更有效地为大型对象(例如包含数百万项的列表)使用内存。一般来说,如果用传统的Python表示,像NumPy中的大型对象将占用大约四分之一的内存。重写Python算法以使用NumPy需要一些工作,因为需要使用NumPy的语法重新声明数组对象。但是NumPy使用Python现有的习语(+、-等)来进行实际的数学运算,因此切换到NumPy应该不会太混乱。4.使用C库NumPy是使用用C编写的库的好方法。如果现有的C库满足您的需求,Python及其生态系统提供了多种选项来链接到该库并利用其提高的速度。最常用的方法是Python的ctypes库。因为ctypes与其他Python应用程序广泛兼容,所以它是最好的起点,但不是唯一的起点。CFFI项目为C.Cython提供了更优雅的接口(见下文第五点),也可用于包装外部库的成本是你必须学习Cython的标记方法。5.转换成Cython如果你速度很快,你应该用C代替python,但是像我这样有python依赖的人,对C有一种天然的恐惧,现在有一个很好的解决方案出来了。Cython允许Python用户轻松获得C的速度。现有的Python代码可以逐步转换为C:首先通过Cython将所述代码编译为C,然后通过添加类型注释以获得更快的速度。不过,Cython不能施展魔法。按原样转换为Cython的代码通常不会比运行速度快15%到50%,因为该级别的大多数优化都集中在减少Python解释器的开销上。仅当为Cython模块提供允许将相关代码转换为普通C的类型注释时,速度增益最大。6.使用多线程由于全局解释器锁(GIL)的存在,Python规定在同一时间只能执行一个线程使用多线程时避免状态问题的时间。它在那里是有充分理由的,但它仍然很烦人。随着时间的推移,GIL的效率有了显着提高(这也是你应该使用python3的原因之一),但核心问题仍然存在。为了解决这个问题,Python提供了一个多处理模块(multiprocessing)来在不同的内核上运行Python解释器的多个进程。状态可以通过共享内存或服务器进程共享,数据可以通过队列或管道在进程实例之间传递。您仍然必须手动管理进程之间的状态。此外,启动多个Python实例并在它们之间传递对象会产生相当多的开销。尽管如此,多处理库还是很有用的。此外,使用C库(例如NumPy)的Python模块和包完全避免了GIL。这是推荐它们以提高速度的另一个原因。7.知道你的库在做什么简单地输入importxyz是多么方便,但是你知道第三方库虽然可以改变你的应用程序的性能,但并不总是朝着好的方向发展。有时,当您添加某个模块时,应用程序反而变慢了,这是来自特定库的模块构成了瓶颈。此外,仔细计算经过的时间也会有所帮助,但有时不是很明显。示例:Pyglet是一个用于创建窗口图形应用程序的库,它会自动启用调试模式,这会极大地影响性能,除非明确禁用。除非您阅读文档,否则您可能永远不会意识到这一点。阅读更多,了解更多。8、注意平台间的速度差异Python跨平台运行,但这并不意味着每个操作系统(Windows、Linux、OSX)的特性都可以在Python下抽象出来。大多数时候,您需要了解平台细节,例如路径命名约定等。但在性能方面了解平台差异也很重要。例如,一些python脚本需要使用WindowsAPI来访问一些特定的应用程序,这也可能会降低运行速度。9.使用pypy运行程序CPython是最常用的Python优化方案,因为它优先考虑兼容性而不是原始速度。对于想把速度放在首位的程序员来说,PyPy是Python更好的解决方案,它配备了JIT编译器来加速代码的执行(编译为C代码)。由于PyPy被设计为CPython的直接替代品,因此它是获得快速性能提升的最简单方法之一。大多数Python应用程序将按原样在PyPy上运行。然而,充分利用PyPy可能需要不断的测试。您会发现长时间运行的应用程序更有可能从PyPy中获得最大的性能提升,因为编译器会随着时间的推移分析执行情况。对于运行和退出的短脚本,CPython更好,因为性能提升不足以克服JIT的开销。10.如果您使用的是python2,请升级到python3。并且没有压倒一切的理由(例如不兼容的模块)坚持使用它,你应该跳到python3。Python3中还有许多Python2.x中没有的构造和优化。例如,Python3.5使async变得不那么复杂,async和await关键字成为语言语法的一部分。Python3.2包括对全局解释器锁的重大升级,它显着改进了Python处理多线程的方式。以上就是十个改进方案。虽然这些方法不一定比C和Java跑得快,但是代码跑得快不取决于语言,而是看人,Python本身不一定是最快的。可以,只要速度够快。如果你今天想要我们的Python教程,请继续关注我们。如果对您有帮助,请在下方点赞或观看。有什么问题可以在下方留言区留言,我们会耐心解答!Python实战宝典(pythondict.com)不只是一个合集欢迎关注公众号:Python实战宝典
