Published: 02 March 2021, 18:00
Any enclosing variable can be shadowed in the local scope without affecting the global one:
v = 'global'
def f():
v = 'local'
print(f'f {v=}')
f()
# f v='local'
print(f'{v=}')
# v='global'
And if you try to use a variable and then shadow it, the code will fail at runtime:
v = 'global'
def f():
print(v)
v = 'local'
f()
# UnboundLocalError: local variable 'v' referenced before assignment
If you want to re-define the global variable instead of locally shadowing it, it can be achieved using global
and nonlocal
statements:
v = 'global'
def f():
global v
v = 'local'
print(f'f {v=}')
f()
# f v='local'
print(f'g {v=}')
# g v='local'
def f1():
v = 'non-local'
def f2():
nonlocal v
v = 'local'
print(f'f2 {v=}')
f2()
print(f'f1 {v=}')
f1()
# f2 v='local'
# f1 v='local'
Also, global
can be used to skip non-local definitions:
v = 'global'
def f1():
v = 'non-local'
def f2():
global v
print(f'f2 {v=}')
f2()
f1()
# f2 v='global'
To be said, using global
and nonlocal
is considered a bad practice that complicates the code testing and usage. If you want a global state, think if it can be achieved in another way. If you desperately need a global state, consider using singleton pattern which is a little bit better.