Conceptually this make sense. I can't tell how its implemented but I can tell why.
When you affect a variable it gets affected in the local scope unless you explicitly tell by using the keyword global
. If you only access it and there is no affectation it will implicitly use the global variable since no local variable is defined.
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
If you do this inside a nested function, class or module the rules are similar:
def main():
y = 10
def access():
print y
def affect():
y = 0
print y
access() # 10
affect() # 0
print y # 10
main()
This is probably saving hours of painful debugging by never overwriting variable of parent scopes unless its explicitly stated.
EDIT
disassembling the python byte code gives us some additional information to understand:
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
We can see that the byte code for the local
function is calling STORE_FAST
and the global_
function calls STORE_GLOBAL
.
This question also explain why its more performant to translate function to byte code to avoid compiling every time the function is called:
Why python compile the source to bytecode before interpreting?