全局变量访问比局部变量慢,因Python按LEGB规则查找时需线性搜索全局命名空间,而局部变量通过栈帧偏移寻址近乎零开销;高频场景应显式绑定为局部变量。

为什么全局变量访问比局部变量慢?
Python 在函数内部查找变量时,会按 local → enclosing → global → built-in 顺序逐层搜索(LEGB 规则)。一旦变量不在局部作用域,解释器就得遍历全局命名空间——这个过程是线性查找,且每次调用都重复执行。尤其在高频循环中,print、len、range 这类内置名如果被意外覆盖成全局变量,还会触发额外的哈希冲突或字典回退逻辑。
把常用全局名显式导入局部作用域
最直接有效的做法:在函数开头用 local_name = global_name 把频繁使用的全局对象(包括内置函数、模块、配置常量)绑定为局部变量。Python 对局部变量的访问是栈帧偏移寻址,几乎零开销。
常见适用场景:
- 循环内反复调用
math.sin、os.path.join等模块函数 - 高频使用
print、len、str等内置函数(尤其在 C 扩展模块中被重定义后) - 读取只读配置如
MAX_RETRY、API_TIMEOUT
示例:
立即学习“Python免费学习笔记(深入)”;
import math
def calc_angles(radians):
sin, cos = math.sin, math.cos # ← 绑定到局部
result = []
for r in radians:
result.append((sin(r), cos(r))) # ← 快速访问
return result
避免在循环内动态访问全局变量
以下写法看似简洁,实则每次迭代都触发全局查找:
THRESHOLD = 0.5
def filter_data(items):
return [x for x in items if x > THRESHOLD] # ← 每次比较都查全局
应改为:
def filter_data(items):
threshold = THRESHOLD # ← 提前绑定
return [x for x in items if x > threshold]
其他易踩坑点:
- 闭包中引用外层函数的变量,若外层变量本身是全局的,仍需额外一层查找
- 使用
exec或eval时,未传入locals参数会导致强制 fallback 到全局命名空间 -
from module import *会污染当前命名空间,增加局部变量查找失败概率
用 dis 验证是否真的消除了全局查找
运行 import dis 后对目标函数调用 dis.dis(func),观察字节码:
- 局部变量访问对应
LOAD_FAST - 全局变量访问对应
LOAD_GLOBAL - 内置名访问对应
LOAD_BUILTIN(但若被覆盖,也会退化为LOAD_GLOBAL)
只要关键路径上没有 LOAD_GLOBAL,就说明优化生效。注意:CPython 的某些 JIT 尝试(如 3.12 的实验性加速)不改变此行为逻辑,仍依赖手动绑定。
真正影响性能的不是“有没有全局变量”,而是“有没有在热路径里反复查它”。绑定一次,一劳永逸;漏掉一个,可能让整段循环慢 15%–30%。



















