Returning Values in Python
Introduction: Functions That Hand Something Back
Welcome to Returning Values and Understanding Scope in Python, and congratulations on reaching the first unit of this course! By now, we can define functions with def, call them whenever we need them, and pass data into them through parameters and arguments. That covers one direction of the conversation: information flowing in.
The other direction is still missing. So far, the only way our functions could share their work with us was by calling print inside the body, which puts text on the screen but leaves the rest of the program empty-handed. In this lesson, we will fix that with the return keyword, covering four ideas:
returnversusprint;- capturing a returned value in a variable;
- using a returned value directly inside a larger expression;
- what happens when a function has no
returnat all.
Here is the four-line output of the small program we will build together:
return Instead of print
Let's start with the simplest possible value-producing function. Its entire body is one statement:
A few details deserve attention here:
- The
returnkeyword lives inside the function body, so it is indented under thedefheader, just like any other statement in the body. - After
returncomes a value or an expression; Python evaluatesa + bfirst, then hands the result back. - There is no
printanywhere in this function. Running this definition, and even callingadd(4, 6)on its own line, would show absolutely nothing on the screen.
That silence is the point. print writes text for a human to read; return sends a value back to the code that made the call. These are different jobs, and mixing them up is the most common confusion for new Python programmers.
Capturing the Returned Value at the Call Site
If add shows nothing, how do we ever see the sum? We catch the value at the call site and print it ourselves:
Let's trace the first line carefully because the order matters:
- Python evaluates the call
add(4, 6), soabecomes4andbbecomes6. - The function computes
10and hands it back withreturn. - That
10takes the place of the call in the expression, so the line effectively becomesresult = 10. - Only then does the assignment happen, storing
10inresult.
The printed line comes from the caller, not from inside add. And since 10 now lives in a variable, we can reuse it as many times as we want without calling add again. Remember the ordering rule from the previous course: the def must appear above the first line that calls it.
Using a Returned Value Directly in an Expression
Storing the value first is convenient, but it is not required. A returned value can be used anywhere a plain value could be used:
Reading this line from the inside out:
add(4, 6)runs and hands back10;- that
10replaces the call, leaving10 * 2; - the multiplication produces
20, which is finally passed toprint.
Notice who is in charge here: the caller decides what to do with the value. Changing * 2 to * 3 would print Doubled: 30 without touching a single character inside add. The same idea works with comparisons or with feeding one call's result straight into another call, which is exactly how we will chain functions together later in this course.
Functions Without a return: Meet None
Now for the contrast. Here is a function that does the opposite of add: it prints but never returns anything.
Two separate things happen on the captured = show_sum(4, 6) line. The text Sum: 10 appears immediately, produced by the print inside the function body. Then execution reaches the end of the body without meeting a return, so Python automatically hands back the special value None. The function still returns; it simply returns nothing useful, and captured is stuck holding None.
That None is more than a cosmetic detail. It is not a number, so writing captured * 2 would immediately crash with TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'.
The Silent Bug: Computing but Forgetting to Return
A far sneakier version of the same problem appears when a function does the math but forgets the final step:
The arithmetic is perfectly right; total inside the function really does hold 15. But computing a value and handing it back are two separate acts, and only the first one happened here. The fix is a final line, return total, and the caller then prints 15.
Keep one companion rule in mind: return immediately ends the function's execution, so any statement written after return total would never run. Before writing a function, it helps to decide deliberately what its job is: to display something, to produce a value, or both. A value-producing function must return on its path.
The Complete Program
Putting all the pieces together, here is the finished script:
Each output line maps to exactly one statement: line one comes from print("Sum:", result), line two from the inline expression, line three from inside show_sum, and line four from the caller printing captured. Note that show_sum is left without a return on purpose as our counterexample, and that this is a plain top-level script: no wrapper function, no imports. We keep flat top-level execution (no main() or __main__ guard) only to keep these beginner demos visually simple; such guards are common when a file is meant to be imported as a module.
Conclusion and Next Steps
The core rule of this lesson fits in four words: print shows, return gives back. Only a returned value can be captured in a variable, reused across several calculations, or dropped straight into a larger expression. A function without a return still hands something back, but that something is None, which cannot be used in arithmetic; and a function that computes a value while forgetting to return it produces the same silent None.
Coming up, we will read the finished program, rebuild it from an empty file, use returned values inline, watch None appear, and repair a function whose missing return quietly breaks its caller. Later in this course, we will look at local scope and see why, for the pure calculation functions we write here, return is the usual way to provide a function's result to its caller.
Time to open the editor and make these functions hand their values back!
