Scope: Local and Global Variables
Expressions and variables can both be passed as arguments to user-defined functions, just as they can be passed to built-in functions.
A Value Before the Function
When you call a function, the information inside the parentheses can be a literal value, a variable, or an expression. User-defined functions accept these forms just as built-in functions do. The key timing rule is simple: Python evaluates each argument exactly once before it calls the function.
What do you think happens?
A function call contains the expression 'Spam ' * 4. What happens first?
Reveal answer
Answer: The expression is computed once, then its result is passed to the function.
Python evaluates the argument before the function is called. The function receives the resulting string, not the unevaluated expression.
The Evaluation Sequence
An expression is a combination of values, operators, and function calls that Python can evaluate to produce a result. When an expression is used as an argument, the expression does not reach the function. Python computes its result first, and the function receives only that result. The computation occurs once during argument evaluation, even if the function later uses the received value more than once.
Tracing an Expression Argument
A Repeated String Passed to print_twice
Determine what value print_twice receives when it is called with the expression 'Spam ' * 4, and determine what the function prints.
Evaluate the argument: Python computes 'Spam ' * 4 once, producing the string 'Spam Spam Spam Spam '.
Pass the result: The resulting string is passed to print_twice. The expression itself is not passed.
Assign the parameter value: Inside print_twice, the parameter bruce holds the resulting string.
Run the function: The function prints the value twice. The string repetition was not performed twice; it was performed once before the call.
The function receives one string value, 'Spam Spam Spam Spam ', and prints that value twice.
The important distinction is between producing the argument and using the argument. The expression produces one string before print_twice begins. The function then uses the already-produced string twice. This distinction helps you predict both the received value and the amount of evaluation work.
Tracing a Variable Argument
A variable holds a value. When a variable is passed as an argument, Python looks up the value stored in that variable and passes the value to the function. The variable name itself is not passed. The receiving parameter therefore gets the stored value rather than the original variable name.
A Stored String Passed to print_twice
Determine what print_twice receives when michael stores the string 'Eric, the half a bee.' and the call uses michael as its argument.
Look up the variable: Python retrieves the string stored in michael.
Pass the stored value: That string is passed to print_twice. The name michael is not passed.
Receive the value: Inside print_twice, the parameter bruce receives 'Eric, the half a bee.'.
Run the function: The function prints the received string twice.
The function receives and prints the stored string value twice, not the variable name michael.
| Argument form | What Python does before the call | What the function receives |
|---|---|---|
| Expression | Computes the expression once | The expression's result |
| Variable | Retrieves the value stored in the variable | The stored value |
A Function Call with math.cos
The argument can itself contain a function call. In math.cos(math.pi), the complete argument is an expression. Python evaluates that expression once before calling print_twice. The result is -1.0, so print_twice receives -1.0. Although print_twice prints the received value twice, math.cos is called only once during argument evaluation.
Mistakes in Evaluation Tracing
Treating an expression as though it is passed unchanged.
Python evaluates an expression before the function is called.
Fix:
Write down the expression's result first, then trace that value into the parameter.Assuming an argument expression is evaluated once for every use inside the function.
The expression is evaluated exactly once before the call. The function receives the resulting value.
Fix:
Separate the one-time argument evaluation from the later uses of the received value.Thinking the variable name is passed to the function.
Python retrieves the value stored in michael and passes that value.
Fix:
Replace the variable reference with the value it stores when tracing the call.Debugging only the function body when the received value is unexpected.
The unexpected value may have arisen during argument preparation before the function began.
Fix:
Trace the argument first, then inspect how the function uses the value.
Debugging with a Four-Step Trace
- Identify whether the argument is a variable or an expression.
- If it is an expression, compute its result once. If it is a variable, identify the value stored in it.
- Record the value that reaches the function parameter.
- Only then trace what the function does with that received value.
This trace separates two possible sources of an unexpected result: preparing the argument and using the received value. If the value is already wrong before the function begins, inspect the expression or variable. If the value is correct at the parameter but the outcome is wrong, inspect the function's use of that value.
Practice the Call Trace
A user-defined function is called with a variable that stores a string. Trace the call without executing it: identify the stored value, state what the parameter receives, and explain why the variable name itself is not the function's input.
Hints
- Start with the value stored in the variable.
- The function receives the value retrieved from the variable.
- The parameter does not receive the variable's name.
A user-defined function receives the result of an expression that includes a function call. Predict the order of events: expression evaluation, parameter receipt, and function-body execution. Then explain how many times the argument expression is evaluated.
Hints
- The argument is evaluated before the function is called.
- The parameter receives the resulting value.
- The argument expression is evaluated exactly once.
Key Takeaways
- User-defined functions can receive literals, variables, and expressions as arguments.
- Python evaluates an argument exactly once before calling the function.
- An expression contributes its result, not the unevaluated expression itself.
- A variable argument contributes the value stored in the variable, not the variable name.
- Tracing argument preparation before tracing the function body helps locate unexpected behavior.
Key Takeaways
- Expressions and variables can both be passed to user-defined functions.
- Arguments are evaluated exactly once before function execution begins.
- The function receives an expression's result or a variable's stored value.
- A reliable debugging trace records the argument value before examining the function body.