从概念上讲,这是有道理的。我不知道它是如何实现的,但我可以说出原因。
当您影响一个变量时,它会在本地范围内受到影响,除非您使用关键字global 明确告知。如果你只访问它并且没有做作,它将隐式使用全局变量,因为没有定义局部变量。
x = 10
def access_global():
print x
def affect_local():
x = 0
print x
def affect_global():
global x
x = 1
print x
access_global() # 10
affect_local() # 0
print x # 10
affect_global() # 1
print x # 10
如果您在嵌套函数、类或模块中执行此操作,则规则类似:
def main():
y = 10
def access():
print y
def affect():
y = 0
print y
access() # 10
affect() # 0
print y # 10
main()
这可能会节省数小时的痛苦调试,除非明确说明,否则永远不会覆盖父范围的变量。
编辑
反汇编python字节码为我们提供了一些额外的信息来理解:
import dis
x = 10
def local():
if False:
x = 1
def global_():
global x
x = 1
print local
dis.dis(local)
print global_
dis.dis(global_)
<function local at 0x7fa01ec6cde8>
37 0 LOAD_GLOBAL 0 (False)
3 POP_JUMP_IF_FALSE 15
38 6 LOAD_CONST 1 (1)
9 STORE_FAST 0 (x)
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
<function global_ at 0x7fa01ec6ce60>
42 0 LOAD_CONST 1 (1)
3 STORE_GLOBAL 0 (x)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
我们可以看到local函数的字节码调用STORE_FAST,global_函数调用STORE_GLOBAL。
这个问题还解释了为什么将函数转换为字节码以避免每次调用函数时都进行编译的性能更高:
Why python compile the source to bytecode before interpreting?