Return Statements in Python- A Complete Guide
What Return Statements Actually Do in Python
A return statement ends a function's execution and sends a value back to wherever the function was called. That's it. No magic, no ceremony.
If you've been using print() when you should have used return, your code is probably broken and you don't even know it yet.
Return vs Print: The Difference That Matters
This trips up beginners constantly. print() displays output to the console. return sends a value back to the program.
See the difference:
def with_print(x):
x * 2
def with_return(x):
return x * 2
result1 = with_print(5)
result2 = with_return(5)
print(result1) # None
print(result2) # 10
The with_print function does the calculation but throws it away. result1 is None because nothing gets sent back.
Returning Nothing: When None Makes Sense
Functions without an explicit return statement return None automatically. This is fine when your function performs an action rather than producing a value.
def log_message(msg):
print(f"[LOG] {msg}")
# implicitly returns None
This function's job is side effects—logging, not calculating. Returning None is correct here.
Multiple Return Values: Python's Tuple Trick
Python functions can return multiple values. They're actually returning a tuple.
def get_stats(numbers):
return min(numbers), max(numbers), sum(numbers)
low, high, total = get_stats([1, 2, 3, 4, 5])
print(low, high, total) # 1 5 15
This is clean syntax for a common pattern. No dictionaries or custom objects needed.
Early Returns: Exiting Functions Prematurely
You can return from anywhere inside a function. This is useful for guard clauses—checking conditions and bailing out early.
def divide(a, b):
if b == 0:
return "Cannot divide by zero"
return a / b
Instead of nested if-else blocks, you check the problem case first and return immediately. Your code stays flat and readable.
Returning Functions: Closures and Decorators
Functions can return other functions. This enables closures and decorators—advanced patterns you'll encounter in real code.
def multiplier(factor):
def inner(number):
return number * factor
return inner
double = multiplier(2)
print(double(5)) # 10
print(double(10)) # 20
multiplier returns the inner function, which remembers the factor value. This is closures in action.
Common Mistakes to Avoid
- Using
print()instead ofreturninside functions meant to produce values - Forgetting that code after a
returnstatement never executes - Returning different types from the same function without good reason
- Modifying mutable arguments and also returning them—pick one approach
The Return Statement Comparison Table
| Statement | Behavior | Use When |
|---|---|---|
return value |
Sends value back, exits function | Function produces a result |
return (bare) |
Returns None, exits function | Early exit, no value needed |
| No return statement | Returns None implicitly | Side-effect-only functions |
return a, b, c |
Returns tuple (a, b, c) | Multiple related values |
How to Start Using Return Statements Correctly
- Identify the function's purpose. Does it compute something or just perform an action?
- If it computes: use
return resultto send the value back - If it performs an action: use
print()or modify data in place, returnNone - Test your function. Assign the function call to a variable and print it
# Wrong approach
def calculate_tax(price, rate):
price * rate / 100 # Result disappears
# Correct approach
def calculate_tax(price, rate):
return price * rate / 100
tax = calculate_tax(100, 20)
print(tax) # 20.0
Return Statements and Generator Functions
Generator functions use yield instead of return. When a generator is exhausted, it raises StopIteration—the return value becomes the exception's value if you catch it.
def count_to_three():
yield 1
yield 2
yield 3
return "done"
gen = count_to_three()
for item in gen:
print(item)
Most of the time you won't need the return value of generators. But it's there if you do.
When Return Values Get Ignored
Python doesn't force you to use a return value. This is valid:
def add(a, b):
return a + b
add(2, 3) # Return value thrown away
This is fine for functions with side effects, but wasteful if the function does actual computation. You're burning CPU cycles for nothing.
Bottom Line
Return statements transfer computed values out of functions. Use them when your function produces something. Don't use print() as a substitute—it's for humans reading output, not for programs getting data.
Get this distinction right early. It eliminates an entire category of bugs from your code.