Scope
In the previous lesson a function was a coffee machine with knobs. Now let's see where the machine stands and what it can see around it.
The machine stands in a café. On the café wall hangs a notice board: every visitor can see it, and so can the machine. Inside, the machine has its own notepad for calculations. It writes intermediate numbers there, and nobody outside can see that notepad.
When an order is ready, the page is torn out of the notepad. The next order starts on a clean sheet. And the key part: if the machine writes a number into its notepad under the same name as one on the board, the board does not change.
Let's see what this looks like in code. A function can read a variable created outside it. But assigning to that variable inside the function changes nothing outside:
level = 1
def show_level():
print(level)
def reset_level():
level = 0
print(level)
show_level() # 1
reset_level() # 0
print(level) # 1Step by step:
level = 1writes on the board: the variable is created outside any function.show_level()readslevelfrom the board and prints1.reset_level()writeslevel = 0into its notepad and prints0.- The last
print(level)looks at the board again and prints1: nobody changed it.
Local and global names
A variable assigned outside any function is global: it is visible in the whole file, including inside functions. That is the board on the wall.
A variable assigned inside a function is local. That is an entry in the notepad. Parameters are local too: the argument values go straight into the call's notepad.
The part of a program where a name is available is called its scope. Local variables appear when the function is called and disappear when it returns. Each call starts with new local variables. Outside the function, its local names do not exist:
def square(x):
result = x * x
return result
print(square(4)) # 16
print(result) # ✗NameError: name 'result' is not definedThe function returned 16, and its notepad with result and x is already thrown away. So two functions can have local variables with the same name, and those variables do not depend on each other.
When a function reads a name that is not in its notepad, Python looks further. For a function defined directly in the file, the order is:
- the call's local variables;
- the file's global variables;
- Python's built-in names, such as
printandabs.
Assignment makes a name local
Here the notepad picture needs a caveat. The machine decides which names go into the notepad in advance, before it starts on the order.
Python decides which names of a function are local before the function is called, from its whole body. If the body assigns a name anywhere, with = or +=, it is local in the whole function. That includes the lines above the assignment and the right side of the assignment itself.
That is why level = 0 in reset_level creates a new local level, and the global one stays 1. The show_level function assigns nothing to the name level. That name is not local to it, and Python takes the global variable.
The global statement
To make a function change a global variable, write global and the name at the start of its body. It is like letting the machine write right on the board. After that, an assignment changes the global variable instead of creating a local one:
calls = 0
def count_call():
global calls
calls += 1
count_call()
count_call()
print(calls) # 2Each call to count_call() adds one to the global calls, so the program prints 2.
Reading does not need global: a function can read a global variable without it. A function that changes global variables is harder to follow: its result depends on more than its arguments. More often, the value is passed in a parameter and the new one is returned with return: calls = add_one(calls).
Common mistake
Interviewers like to ask this: what happens if you increase a global variable inside a function without global?
score = 0
def add_point():
score += 1 # ✗
print("before") # before
add_point()UnboundLocalError: cannot access local variable 'score' where it is not associated with a valueBecause of +=, the name score is local in the whole function. To add 1, Python reads the local score, which has no value yet. The file check does not catch this, so before is printed, and the error comes on the call.
There are two ways to fix it:
- add
global scoreas the first line of the body; - pass the score in a parameter and return the new one.
Key points
- A variable created outside functions is global; one created inside a function, and parameters, are local.
- Local variables live only during the call; outside it they do not exist.
- An assignment anywhere in the body makes a name local in the whole function.
- To change a global variable, write
global nameat the start of the body.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.