Here is an example code that I have made to try to understand the mechanics of "nonlocal" keyword. `
# Outer fuction
def func1():
var1 = 2
print("---ID of var1 in func1---")
print(id(var1))
print(locals())
# Inner function
def func2():
nonlocal var1
var1 += 1
print("---ID of var1 in func2---")
print(id(var1))
print(locals())
# Call inner function
func2()
print("---ID of var1 in func1 after func2 execution---")
print(id(var1))
print(locals())
func1()
` We define var1 in func1() namespace. After calling 'nonlocal' in func2(), var1 changes its id and start to appear in local dictionary of func2(). After execution of func2(), it is still exists in local dictionary of func1().
Does it mean that a variable can exist in several namespaces in the same time? Why did id(var1) changed?
I expected that var1 will be only in local dictionary of func1() and 'nonlocal' keyword will just give a possibility to change it in func2().
locals()
is a very weird function that doesn't do what anyone would reasonably expect it to, with some bizarre undocumented quirks. This particular quirk happens to be documented, but it's still really weird. Generally, you shouldn't uselocals()
unless you really have no other choice.The dict returned by
locals()
isWhen called inside a function, the dict returned by
locals()
will include nonlocal variables:That doesn't mean the variable actually exists in multiple namespaces at the same time. It means
locals()
is weird.As for the ID change, IDs are associated with objects, not variables. The integer object
var1
refers to aftervar1 += 1
is a different object with a different ID than the previous integer object.