为什么 Python 代码在函数中运行得更快?

发表于:2023-9-26 09:28

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:咸鱼不想秃头    来源:咸鱼运维杂谈

  要理解为什么 Python 代码在函数中运行得更快,我们需要首先了解 Python 是如何执行代码的。
  我们知道,python 是一种解释型语言,它会逐行读取并执行代码。
  当运行一个 python 程序的时候,首先将代码编译成字节码(一种更接近机器码的中间语言)然后 python 解释器执行字节码。
  由上所示,python 中的 dis 模块将函数 hello_world 分解为字节码。
  需要注意的是,python 解释器是一个执行字节码的虚拟机,默认的 python 解释器是用 C 编写的,即 CPython
  还有其他的 python 解释器如 Jython(用 Java 编写),IronPython(用于 .net)和PyPy(用 Python 和 C 编写)
  为什么 python 代码在函数中运行得更快
  我们来编写一个简单的例子:定义一个函数 my_function,函数内部包含一个 for 循环
  编译该函数的时候,字节码可能如下所示:
  这里的关键指令是 STORE_FAST ,用于存储循环变量 i。
  现在我们把这个 for 循环放在 python 脚本的顶层(全局范围内),然后再来看一下字节码:
  可以看到关键指令变成了 STORE_NAME,而不是 STORE_FAST。
  字节码 STORE_FAST比 STORE_NAME 快,因为在函数中,局部变量存储在固定长度的数组中,而不是存储在字典中。这个数组可以通过索引直接访问,使得变量检索非常快。
  基本上,它只是一个指向列表的指针,并增加了 PyObject 的引用计数,这两个都是高效的操作。
  另一方面,全局变量存储在一个字典。当访问全局变量时,Python 必须执行哈希表查找,这涉及计算哈希值,然后检索与之关联的值。
  虽然经过优化,但仍然比基于索引的查找慢。
  基准测试验证
  我们知道在 Python 中,代码执行的速度取决于代码执行的位置——在函数中还是在全局作用域中。
  让我们用一个简单的基准测试的例子来比较一下。
  首先定义一个求阶乘的函数。
  然后在全局范围内执行相同的代码:
  为了对这两段代码进行基准测试,我们可以在 Python 中使用 timeit 模块,它提供了一种简单的方法来对少量 Python 代码进行计时。
  可以看到,函数代码的执行速度比全局作用域代码要快。
  需要注意的是,这两段代码最好不要放在同一脚本中,要分开单独运行。
  这是因为 benchmark() 函数在执行时间上增加了一些开销,并且全局代码在内部进行了优化。
  cProfile 分析
  python 提供了一个  cProfile 内置模块。
  让我们用它来分析一个新例子:在局部和全局范围内计算平方和。
  上面的例子中,可以认为sum_of_squares_g() 函数是全局的,因为它使用了两个全局变量, i 和 total。
  从性能分析结果中,可以看到函数代码在执行时间方面比全局更有效。
  如何优化 python 函数的性能
  前面我们知道,Python 代码在函数中运行往往比在全局范围内运行要快得多。
  如果想要进一步提高 python 函数代码效率,不妨考虑一下使用局部变量而不是全局变量。
  另一种方法是尽可能使用内置函数和库。Python 的内置函数是用 C 实现的,比 Python 快得多。
  比如 NumPy 和 Pandas,也是用 C 或 C++ 实现的,它们比实现同样功能的 Python 代码速度更快。
  又比如同样是实现数字求和的功能,python 内置的 sum 函数要比你自己编写函数速度更快。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号