The Python return statement is one of the most important concepts to understand when you start writing real functions. Beginners often learn print() first, so it is natural to think that showing a value on the screen is the same as giving that value back to the program. It is not. A printed value is only displayed. A returned value can be stored, tested, passed to another function, reused, transformed, or sent back from an API.
This English version is adapted for developers who want a practical explanation, not a literal translation. You will learn what return does, why it stops a function, how it differs from print(), how to return multiple values, why functions sometimes return None, and how to use return statements to write cleaner, testable Python code. If you are still learning the basics, start with this Python beginner guide and this guide to functions in Python.
What Does return Do in Python?
In Python, return sends a value from inside a function back to the code that called that function. A function can receive input through parameters, process that input, and return an output. That output becomes available to the rest of your program. This is the difference between a function that only performs an action and a function that produces a reusable result.
def add(a, b):
return a + b
result = add(10, 5)
print(result) # 15
print(result * 2) # 30The function add() does not print anything by itself. It returns the calculated value. Because the result is returned, the caller can store it in a variable and use it later. That makes the function reusable in scripts, applications, tests, APIs, data pipelines, and other functions.
The official Python documentation explains return as the statement that leaves the current function call and optionally passes back an expression value. You can read the formal definition in the Python language reference.
return Stops the Function Immediately
A return statement does two things. First, it sends a value back to the caller. Second, it exits the function immediately. Any code placed after a return statement in the same execution path will not run. This is why return is also used to stop a function early when a condition has already been handled.
def check_age(age):
if age < 18:
return "Access denied"
return "Access granted"
print(check_age(16))
print(check_age(25))When age is less than 18, Python returns "Access denied" and leaves the function. It does not continue to the final line. This early-exit pattern keeps code simple because you can handle invalid cases first and let the normal path remain easy to read. If conditional logic still feels confusing, review this guide on programming logic with Python.
return vs print: The Key Difference
The most common beginner mistake is confusing return with print(). The print() function displays information in the terminal. The return statement gives information back to the caller. A value printed to the screen is not automatically available for calculations, comparisons, tests, or other functions.
def add_with_print(a, b):
print(a + b)
def add_with_return(a, b):
return a + b
x = add_with_print(5, 5)
y = add_with_return(5, 5)
print(x) # None
print(y) # 10
print(y * 2) # 20The first function displays 10, but it does not return 10. Because no explicit return value exists, Python returns None. The second function returns the value, so it can be multiplied, stored, or passed into another function. Understanding None in Python is essential because many confusing bugs come from expecting a function to return data when it only prints data.
Functions Return None by Default
Every Python function returns something. If you do not write a return statement, Python returns None automatically. This is normal for functions that only perform an action, such as writing a file, sending a notification, or printing a message. But it becomes a bug when you expected a usable value.
def greet(name):
message = f"Hello, {name}!"
result = greet("Ana")
print(result) # NoneThe variable message exists only inside the function. Because the function never returns it, the caller receives None. To make the message available outside the function, return it:
def greet(name):
message = f"Hello, {name}!"
return message
result = greet("Ana")
print(result)This is where variable scope matters. Values created inside a function do not automatically become available everywhere else. If that topic is new, read this explanation of variable scope in Python.
Returning Multiple Values
Python makes it easy to return multiple values. When you separate values with commas after return, Python returns them as a tuple. You can then unpack that tuple into separate variables. This is useful when a function naturally produces more than one result, such as minimum, maximum, and average values.
def get_stats(numbers):
minimum = min(numbers)
maximum = max(numbers)
average = sum(numbers) / len(numbers)
return minimum, maximum, average
low, high, avg = get_stats([10, 20, 30, 40])
print(low)
print(high)
print(avg)This syntax is concise, but use it carefully. If a function returns too many unrelated values, a dictionary, data class, or object may be clearer. For small related groups of values, tuple unpacking is clean and idiomatic. To understand the structure behind this behavior, review tuples in Python and Python lists.
Returning Early with Guard Clauses
Return statements are often used as guard clauses. A guard clause checks for an invalid or special case at the beginning of a function and returns immediately. This avoids deep nesting and makes the main logic easier to read. Instead of wrapping everything inside large if blocks, you handle the edge cases first.
def calculate_discount(price, percentage):
if price <= 0:
return 0
if percentage <= 0:
return price
discount = price * (percentage / 100)
return price - discountThis function is easy to scan. Invalid prices return 0. Invalid discounts return the original price. The normal calculation happens only after those cases are handled. This pattern appears frequently in APIs, form validation, automation scripts, and data processing functions. It is also a useful habit for writing clean code, as discussed in these Python best practices.
Returning Different Data Types
Python lets you return any object: strings, numbers, lists, dictionaries, tuples, booleans, functions, class instances, or None. This flexibility is powerful, but it can also make code confusing when a function returns inconsistent types. For example, a function that sometimes returns a list and sometimes returns a string error message can be difficult to use safely.
# Harder to work with
def find_users(active_only=True):
if active_only:
return ["Ana", "Bruno"]
return "No filter applied"In most cases, prefer consistent return types. A function that returns a list should return an empty list when there are no results, not a string. A function that returns a dictionary should document its keys clearly. Consistency makes code easier to test and reduces surprise. If type behavior is still unclear, this guide to Python data types is a useful next step.
Using return with Boolean Logic
A function can return the result of a comparison directly. This is useful for validation functions because comparisons already produce True or False. You do not need to write a full if statement when the expression itself already answers the question.
def is_adult(age):
return age >= 18
print(is_adult(16)) # False
print(is_adult(21)) # TrueThis style is short and readable when the condition is simple. If the condition becomes complex, assign intermediate names or use multiple guard clauses. Compact code is not always better. The goal is clarity.
Returning Functions from Functions
Because functions are objects in Python, you can return a function from another function. This idea appears in decorators, closures, factories, and advanced configuration patterns. You may not need this every day as a beginner, but recognizing it helps you understand more professional Python code later.
def make_multiplier(factor):
def multiply(number):
return number * factor
return multiply
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(10))
print(triple(10))The function make_multiplier() returns another function. The returned function remembers the value of factor. This concept is closely related to Python decorators, where one function often returns a wrapper function.
return Inside Loops
A return statement inside a loop exits the entire function, not just the loop. This can be exactly what you want when searching for the first match. It can also be a bug when you accidentally return during the first iteration. Always check indentation carefully when a function returns earlier than expected.
def find_first_even(numbers):
for number in numbers:
if number % 2 == 0:
return number
return None
print(find_first_even([1, 3, 5, 8, 9]))This function stops as soon as it finds the first even number. If no even number exists, it returns None after the loop finishes. That final return matters because it makes the “not found” case explicit. If loops are still a weak point, review the basics of loops in Python.
Adding Type Hints to Return Values
Type hints make return values easier to understand. They do not change runtime behavior by themselves, but they help editors, static analysis tools, and other developers understand what a function is expected to return. This is especially useful in larger projects where functions are reused across multiple files.
def format_username(name: str) -> str:
return name.strip().lower()
def divide(a: float, b: float) -> float | None:
if b == 0:
return None
return a / bThe arrow syntax indicates the expected return type. In the second function, float | None communicates that the function may return a number or None. This makes the function safer to use because the caller knows it must handle the zero-division case. For more examples, read this guide to Python type hints.
Common Mistakes with return
The first mistake is using print() when you need return. The second is forgetting a return statement and accidentally getting None. The third is returning too early inside a loop because of wrong indentation. The fourth is returning inconsistent data types. The fifth is writing code after a return statement and expecting it to run.
Another common mistake is assuming return belongs everywhere. Some functions are designed only to perform side effects, such as writing a file or logging a message. Those functions may not need a meaningful return value. The important part is being intentional. A function should either return useful data or clearly perform an action.
Best Practices for Clean Return Statements
Keep return values consistent. Use guard clauses to handle invalid input early. Avoid hiding too much logic inside a single return line when it harms readability. Document what your function returns, especially when returning dictionaries, tuples, or optional values. Prefer returning data over printing when you want code to be reusable and testable.
The PEP 8 style guide also recommends consistency when returning values. If a function returns a value in one branch, make sure other branches are clear as well. This avoids confusing functions where some paths return useful data and other paths accidentally return None.
Final Checklist
Use return when a function needs to give a value back to the caller. Remember that return exits the function immediately. Use print() only when you want to display information, not when you need reusable data. Return multiple values with commas when the values are closely related. Handle None intentionally. Use type hints and documentation when the return value is important for other parts of the project.
Once you understand return, your Python functions become more powerful. You stop writing scripts that only show output and start writing reusable building blocks. That is the difference between code that works once and code that can support real applications, tests, APIs, automation workflows, and larger projects.






