Read the following code. Can you predict what it will do when you run it?
| | >>> def f(x): |
| | ... x = 2 * x |
| | ... return x |
| | ... |
| | >>> x = 1 |
| | >>> x = f(x + 1) + f(x + 2) |
That code is confusing, mainly because the variable x is used repeatedly throughout the code. However, it is short and only uses Python features that you have seen so far: assignment statements, expressions, function definitions, and function calls. You’re missing some information: Are all the x’s the same variable? Does Python make a new x for each assignment? For each function call? For each function definition?
Here’s the answer: whenever Python executes a function call, it creates a namespace (literally, a space for names) for the local variables for that call. You can think of a namespace as a scrap piece of paper; Python writes down the local variables on that piece of paper, keeps track of them as long as the function is being executed, and throws that paper away when the function returns.
Separately, Python keeps another namespace for the variables created in the shell. The variable x, which is a parameter of the function f, is a different variable from the x in the shell!
Let’s refine your rules from , for executing a function call to include this namespace creation:
Evaluate the arguments left to right.
Create a namespace to hold the function call’s local variables, including the parameters.
Pass the resulting argument values into the function by assigning them to the parameters.
Execute the function body. As before, when a return statement is executed, execution of the body terminates, and the value of the expression in the return statement is used as the value of the function call.
From now on, in the memory model, we will draw a separate box for each namespace to indicate that the variables inside it are in a separate area of computer memory. Programmers refer to this box as a frame. We separate the frames from the objects by a vertical dotted line:

Using your newfound knowledge, let’s trace that confusing code. Initially, no variables have been created; Python is about to execute the function definition. We have indicated this with an arrow:
| » | >>> def f(x): |
| | ... x = 2 * x |
| | ... return x |
| | ... |
| | >>> x = 1 |
| | >>> x = f(x + 1) + f(x + 2) |
As you’ve seen in this chapter, when Python executes that function definition, it creates a variable f in the frame for the shell’s namespace plus a function object. (Python didn’t execute the body of the function; that won’t happen until the function is called.) Here is the result:

Now let’s execute the first assignment to x in the shell.
| | >>> def f(x): |
| | ... x = 2 * x |
| | ... return x |
| | ... |
| » | >>> x = 1 |
| | >>> x = f(x + 1) + f(x + 2) |
Once that assignment happens, both f and x are in the frame for the shell:

Now you are about to execute the second assignment to x in the shell:
| | >>> def f(x): |
| | ... x = 2 * x |
| | ... return x |
| | ... |
| | >>> x = 1 |
| » | >>> x = f(x + 1) + f(x + 2) |
Following the rules for executing an assignment from , you first evaluate the expression on the RHS, which is f(x + 1) + f(x + 2). Python evaluates the left function call first: f(x+1).
Following the rules for executing a function call, Python evaluates the argument, x + 1. To find the value for x, Python looks in the current frame. The current frame is the frame for the shell, and its variable x refers to 1, so x + 1 evaluates to 2.
Now you have evaluated the argument to f. The next step is to create a namespace for the function call. We draw a frame, write in parameter x, and assign 2 to that parameter:

Notice that there are two variables called x, and they refer to different values. Python will always look in the current frame, which we will draw with a thicker border.
You are now about to execute the first statement of the function f:
| | >>> def f(x): |
| » | ... x = 2 * x |
| | ... return x |
| | ... |
| | >>> x = 1 |
| | >>> x = f(x + 1) + f(x + 2) |
x = 2 * x is an assignment statement. The RHS is the expression 2 * x. Python looks up the value of x in the current frame and finds 2, so that the expression evaluates to 4. Python finishes executing that assignment statement by making x refer to that 4:

You are now about to execute the second statement of the function f, a return statement:
| | >>> def f(x): |
| | ... x = 2 * x |
| » | ... return x |
| | ... |
| | >>> x = 1 |
| | >>> x = f(x + 1) + f(x + 2) |
You evaluate the expression, which is simply x. Python looks up the value for x in the current frame and finds 4, so that is the return value:

When the function returns, Python evaluates this expression: f(x + 1) + f(x + 2). Python just finished executing f(x + 1), which produced the value 4. It then executes the right function call: f(x + 2).
Following the rules for executing a function call, Python evaluates the argument, x + 2. To find the value for x, Python searches the current frame. The call to function f has returned, so that frame is erased. The only frame left is the frame for the shell, and its variable x still refers to 1; therefore, x + 2 evaluates to 3.
Now you have evaluated the argument to f. The next step is to create a namespace for the function call. We draw a frame, write in the parameter x, and assign 3 to that parameter:

Again, you have two variables called x.
You are now about to execute the first statement of the function f:
| | >>> def f(x): |
| » | ... x = 2 * x |
| | ... return x |
| | ... |
| | >>> x = 1 |
| | >>> x = f(x + 1) + f(x + 2) |
x = 2 * x is an assignment statement. The right side is the expression 2 * x. Python looks up the value of x in the current frame and finds 3, so that expression evaluates to 6. Python finished executing that assignment statement by assigning 6 to x:

You are now about to execute the second statement of the function f, a return statement:
| | >>> def f(x): |
| | ... x = 2 * x |
| » | ... return x |
| | ... |
| | >>> x = 1 |
| | >>> x = f(x + 1) + f(x + 2) |
You evaluate the expression, which is simply x. Python looks up the value for x in the current frame and finds 6, so that is the return value (as shown in the ).

When the function returns, Python evaluates this expression: f(x + 1) + f(x + 2). Python just finished executing f(x + 2), which produced the value 6. Both function calls have been executed, so Python applies the + operator to 4 and 6, giving you 10.
You have now evaluated the right side of the assignment statement; Python completes it by making the variable on the LHS, x, refer to 10:

Phew! That’s a lot to keep track of. Python does all that bookkeeping for you, but to become a good programmer, it’s essential to understand each step.