def, return, None, and Call Flow
Key Takeaways
- A def statement creates a function object; the function body does not run until the function is called.
- A function that reaches the end without returning a value returns None implicitly.
- print() displays output for a human, while return sends a value back to the caller.
- Code after an executed return statement in the same function call is skipped.
- Nested function calls are evaluated from the inside outward before the outer call receives its arguments.
Why call flow matters
PCEP code-reading questions rarely ask you to write a large function. They ask what a short function prints, returns, or raises. To answer correctly, separate three moments: Python reads the def statement, the program calls the function, and the caller uses the returned value.
A def statement binds a name to a function object. The indented body is stored, not executed immediately. The body runs only when the function name is followed by parentheses, with the required arguments.
def double(n):
print('inside')
return n * 2
print('before')
value = double(4)
print(value)
The output is before, then inside, then 8. The assignment receives the return value 8; it does not receive the word printed inside the function.
return versus print
| Feature | print() | return |
|---|---|---|
| Main job | Writes text to standard output | Sends a value to the caller |
| Usable in expression | Returns None | Returned value can be stored or combined |
| Ends the function | No | Yes, for that call |
| Common PCEP trap | Assuming printed text is the result | Missing code skipped after return |
A function can print and return in the same call, but those actions are different. If a question asks for output, count printed text. If it asks for a value assigned to a variable, follow the return value.
def label(x):
print('item', x)
result = label(3)
print(result)
This prints item 3 and then None. The function has no explicit return statement, so Python supplies None when the body ends.
Implicit None and early exit
There are three common ways a function returns None:
- It has no return statement.
- It executes a bare
returnwith no expression. - It falls through a branch where no return statement is reached.
def sign(n):
if n > 0:
return 'positive'
if n == 0:
return
print(sign(5))
print(sign(0))
print(sign(-2))
The calls print positive, None, and None. The negative call reaches the end of the function body. The zero call executes a bare return. Both return None, but for different paths.
Reading nested calls
When calls are nested, resolve the innermost call first. Then pass its return value outward.
def add_one(n):
return n + 1
def show(n):
print(n)
return n * 10
answer = show(add_one(2))
First add_one(2) returns 3. Then show(3) prints 3 and returns 30. Finally, answer becomes 30.
A name without parentheses is just a reference to the function object. show is not the same operation as show(3). If a snippet stores tool = show, no body has run yet; the call occurs only when tool(...) is executed later.
Exam tracing routine
Use this small checklist on every function snippet:
- Mark every function definition and do not execute its body yet.
- Find the first actual call.
- Bind arguments to parameters for that call.
- Trace until return, error, or the end of the function.
- Replace the call expression with the returned value.
This method keeps you from treating print output, function objects, and return values as the same thing. On PCEP, that distinction is often the whole question.
What does a Python function return if it finishes without executing a return statement?
In a PCEP output question, why is print() different from return?
Given def f(): return 2; print(3), what happens to print(3) during a call to f()?