在Python字节码中,LOAD_NAME
和LOAD_GLOBAL
都是用来加载一个名称引用的值的,但它们在不同的上下文中使用,它们的查找逻辑也略有不同。
-
LOAD_NAME:
- 这条指令在函数体内部使用。
- 它首先尝试在局部变量中查找给定的名称。
- 如果在局部变量中没有找到,它会尝试在全局变量中查找。
- 如果在全局变量中也没有找到,它会尝试在内建命名空间(即
builtins
模块)中查找。 - 如果在所有这些地方都没有找到,则会引发
NameError
。
-
LOAD_GLOBAL:
- 这条指令在函数体内部使用,但仅当知道名称不是局部变量时。
- 它直接从全局命名空间或内建命名空间中查找名称。
- 如果在这两个地方都没有找到,则会引发
NameError
。
这两个指令的区别反映了Python名称解析的LEGB规则,即Local(局部) -> Enclosing(封闭) -> Global(全局) -> Built-in(内建)。但是,请注意,封闭命名空间在这两个指令中并没有直接涉及;它通过LOAD_DEREF
和其他指令处理。
为了更好地理解,考虑以下代码:
x = 10
def foo():
y = 20
print(x) # 使用 LOAD_GLOBAL
print(y) # 使用 LOAD_NAME
foo()
在函数foo
内部,print(x)
使用了LOAD_GLOBAL
指令来加载全局变量x
,而print(y)
使用了LOAD_NAME
指令来加载局部变量y
。