Python Scope
Scope determines where in your program a variable can be seen and used, and Python decides this by where the variable is created.
Local and global scope
A variable created inside a function belongs to that function's local scope and exists only while the function runs. A variable created at the top level of a file lives in the global scope and can be read from anywhere, including inside functions. Keeping variables local by default helps prevent one part of a program from accidentally changing another.
A local variable stays inside its function
def show():
message = "inside" # local variable
print(message)
show() # inside
print(message) # NameError: name 'message' is not definedReading globals from inside a function
A function can read a global variable without any special syntax. Trouble only arises when you try to assign to that name: by default, assigning inside a function creates a new local variable instead of changing the global one.
Reading works, but assigning creates a local
count = 10
def read_it():
print(count) # reads the global: 10
def shadow_it():
count = 99 # this is a new local, not the global
print(count) # 99
read_it()
shadow_it()
print(count) # still 10The global keyword
When you genuinely need a function to change a global variable, declare it with the global keyword before assigning to it. This tells Python to use the existing global name instead of creating a local one. Use this sparingly, since functions that modify globals can be harder to follow.
Modifying a global on purpose
total = 0
def add(amount):
global total
total += amount
add(5)
add(3)
print(total) # 8Nested functions and nonlocal
When one function is defined inside another, the inner function can read variables from the enclosing function. To reassign such an enclosing variable, use the nonlocal keyword, which is the counterpart to global for a surrounding function rather than the module level.
Reaching an enclosing variable with nonlocal
def counter():
n = 0
def step():
nonlocal n
n += 1
return n
return step
next_value = counter()
print(next_value()) # 1
print(next_value()) # 2