为什么 Python 代码在函数中运行得更快
当谈到编程效率和性能优化时,Python 常常被调侃为'慢如蜗牛'。有趣的是,在实际开发中发现,Python 代码在函数内部运行往往比在全局范围内(脚本顶层)运行要快得多。很多开发者可能会疑惑:为什么在函数中运行的 Python 代码速度更快?
Python 执行机制简述
要理解这一现象,首先需要了解 Python 是如何执行代码的。Python 是一种解释型语言,它会逐行读取并执行代码。当运行一个 Python 程序时,首先将源代码编译成字节码(一种更接近机器码的中间语言),然后 Python 解释器执行这些字节码。
需要注意的是,Python 解释器是一个执行字节码的虚拟机。默认的 Python 解释器是 CPython,它是用 C 编写的。此外还有 Jython(用 Java 编写)、IronPython(用于 .NET)和 PyPy(用 Python 和 C 编写)等其他实现。
Python 中的 dis 模块可以将函数分解为字节码指令,帮助我们查看底层执行细节。
局部变量与全局变量的存储差异
我们来通过一个简单的例子来对比。定义一个函数 my_function,函数内部包含一个 for 循环。
def my_function():
for i in range(100):
pass
编译该函数时,生成的字节码中包含关键指令 STORE_FAST,用于存储循环变量 i。这表示变量存储在局部作用域的快速数组中。
现在,我们将同样的 for 循环放在 Python 脚本的顶层(全局范围内):
for i in range(100):
pass
再次查看其字节码,可以看到关键指令变成了 STORE_NAME,而不是 STORE_FAST。
核心原因分析
字节码 STORE_FAST 比 STORE_NAME 快,原因在于变量存储机制的不同:
- 局部变量:在函数中,局部变量存储在固定长度的数组中。这个数组可以通过索引直接访问,使得变量检索非常快。本质上,它只是一个指向列表的指针,并增加了 PyObject 的引用计数,这两个都是高效的操作。
- 全局变量:全局变量存储在一个字典(哈希表)中。当访问全局变量时,Python 必须执行哈希表查找,这涉及计算哈希值,然后检索与之关联的值。虽然经过优化,但仍然比基于索引的查找慢。
因此,减少全局变量的使用,尽量使用局部变量,是提升 Python 代码性能的关键策略之一。
基准测试验证
为了量化这种差异,我们可以使用 Python 内置的 timeit 模块对代码进行计时。
函数内执行
def factorial(n):
result = 1
for i (, n + ):
result *= i
result
(timeit.timeit(, setup=, number=))


