Functions, call frames and returned results
Introduced| English | Meaning |
|---|---|
| function/ˈfʌŋkʃn/ | A mapping that assigns exactly one output to each allowed input. |
| side effect/saɪd ɪˈfekt/ | Anything a function does besides returning a value, such as printing or changing a global. |
| contract/ˈkɒntrækt/ | The stated agreement of what callers may supply and what a function promises in return. |
| parameter/pəˈræmɪtə/ | A named input in a function or procedure definition that receives a supplied argument when it is called. |
| argument/ˈɑːɡjuːmənt/ | Values or references supplied to a function or procedure when it is called. |
| call frame/kɔːl freɪm/ | One paused function call: its own variables, waiting for the callee to return a value. |
| scope/skəʊp/ | The region of a program in which a particular name or binding can be accessed. |
| local variable/ˈləʊkl ˈveərɪəbl/ | A variable whose name is accessible only within a particular function, block or other limited scope. |
| decomposition/ˌdiːkɒmpəˈzɪʃn/ | The breakdown of a substance or system into simpler components. |
Give each function one clear job
- A function 函数 groups a named task. State its inputs, its returned result and any side effect 副作用, such as printing, before writing the body.
- A contract 契约 says what callers may supply and what the function promises. Here, amounts are whole pence and must be non-negative integers.
def add_fee(amount):
"""Return amount plus a fixed fee of 3 pence."""
return amount + 3
add_fee(8) evaluates to 11. It does not print anything. Keeping calculation separate from display lets another function reuse the result.
Which contract lets another calculation use the fee-inclusive amount directly?
Difficulty 1/5 · 100 coins + a small bonus on first completion today
A returned result can be used in an expression; printed output is a separate side effect.
Distinguish the input name from the input object
- In a definition,
amountis a parameter 形参. Inadd_fee(8), the expression8supplies an argument 实参. Argument expressions are evaluated before the function body runs. - The call binds the parameter name to the supplied object. It does not automatically copy that object or create a link between the caller's name and the parameter's name.
amount = 4
result = add_fee(amount * 2)
print(amount, result)
The argument expression gives 8; inside the call, amount refers to that integer. The returned 11 becomes result. The module's amount still refers to 4, so the output is 4 11.
Match each term to its role in add_fee(8).
Difficulty 2/5 · 140 coins + a small bonus on first completion today
The argument is evaluated at the call; its object is bound to the parameter; return hands a result back.
Keep a separate frame for each call
- A call frame 调用帧 records one active function call, including its parameters and local names. When one function calls another, the caller waits for the returned value.
- Read this program in execution order: module →
twice→add_fee→twice→ module. The arrows below are conceptual control flow, not a physical memory layout.
def twice(amount):
subtotal = amount * 2
return add_fee(subtotal)
amount = 4
result = twice(amount)
print(amount, result)

Use the trace to inspect the calls and returns. The frame details show the state at the nested call. It is an authored trace of this exact example, not a Python interpreter.
Trace twice(4) calling add_fee(8)
Separate local bindings from returned values.
Put these events in the order followed by result = twice(4).
Difficulty 3/5 · 200 coins + a small bonus on first completion today
The nested call finishes before twice can finish its return expression.
What integer is bound to amount inside add_fee during this nested call?
Difficulty 2/5 · 140 coins + a small bonus on first completion today
twice calculates subtotal as 4 times 2, then passes that 8 to add_fee.
Return a result; print a message
returnends the current call and gives an object back to the caller. A function that reaches its end withoutreturngivesNone.printwrites output. It also returnsNone, so printing a calculation inside a function does not make that calculation its returned result.
def show_fee(amount):
print(amount + 3)
value = show_fee(8)
print(value)
This prints 11, then None, on separate lines. If the caller needs the number, use return amount + 3 and let the caller decide whether to print it.
show_fee prints 11 but has no return statement. What is stored in value?
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Falling off the end of a Python function returns None, regardless of printed output.
Resolve names in the right scope
- A local variable 局部变量 belongs to a function call. Its scope 作用域 determines where a name can be resolved; another function does not receive access to the caller's local names automatically.
- Assigning a parameter a new integer changes its local binding. It does not reassign a same-named variable in the caller.
def increase(amount):
amount = amount + 1
return amount
amount = 4
new_amount = increase(amount)
print(amount, new_amount)
The output is 4 5. Both names begin by referring to the integer 4; the assignment inside the function rebinds its local name. To update the module name, write amount = increase(amount).
After new_amount = increase(amount), what value does the module's amount still hold?
Difficulty 2/5 · 140 coins + a small bonus on first completion today
Only the function's local name was rebound; the caller did not assign to amount.
Decompose a calculation into testable pieces
- Decomposition 分解 separates a larger task into smaller jobs with clear contracts. For an order, calculate an item subtotal, add a fee, then display the final amount.
- Test calculations directly, including zero quantity and more than one item. State that inputs are non-negative integers; input validation can be a separate function.
def item_subtotal(unit_pence, quantity):
return unit_pence * quantity
def order_total(unit_pence, quantity):
return add_fee(item_subtotal(unit_pence, quantity))
order_total(5, 2) gives 13; order_total(5, 0) gives 3 under this fixed-fee contract. If zero-item orders should cost zero, change the contract and implementation together.
Under the stated fixed-fee contract, what does order_total(5, 0) return in pence?
Difficulty 2/5 · 140 coins + a small bonus on first completion today
The item subtotal is zero, but add_fee still adds 3. Free empty orders require a different contract.
Explain the whole call before trusting the answer
- Trace the argument expressions, parameter bindings, local calculations and returned values. Check the caller's state after the call and the output separately.
- Do not describe parameter passing as copying every object. A mutable collection can be changed through a parameter; object diagrams for mutation and aliasing follow in unit 1.5.
A correct printed number does not prove a correct returned result. Use direct checks such as assert order_total(5, 2) == 13, then inspect any expected output separately.
Language references: Python functions and name binding and scope.
Calling a Python function automatically copies every argument object.
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Parameters are bound to supplied objects. Copying must be requested explicitly when needed.