Definition
Computing a result inside a function is not much use if it stays locked where it was produced. For the rest of the program to print it, compare it, or reuse it, the function has to hand it back when it finishes. That is the role of return: it stops the function and sends a value out to whatever called it.
Here is a function that computes a price including tax and sends it back, instead of just printing it.
def price_with_tax(net, rate=0.20):
return round(net * (1 + rate), 2)
total = price_with_tax(100) # total is 120.0The result, once returned, becomes an ordinary value that can be stored in a variable, compared to a threshold, or handed to another function. That reuse is exactly what separates a function that computes from a function that merely acts, like printing a message or writing to a file.
Anything following a return in the same block never runs. A function may hold several of them, each on a different path depending on the conditions it meets, but only one will run per call.
The print trap
This is the single most common mistake early on, and it rarely gets explained clearly. Many people write a function with print inside it, then try to capture what it printed into a variable, without success. The issue is not carelessness: the two instructions look alike on screen while doing different things.
print shows text in the console while the program runs, a passing display meant for the eyes of whoever is running the code. return hands a value back to the program itself, so it can keep using it after the call ends. Here are the two functions, side by side.
def double_shows(n):
print(n * 2)
def double_returns(n):
return n * 2
a = double_shows(5) # shows 10, but a is None
b = double_returns(5) # shows nothing, but b is 10The variable a never holds the 10 that was printed to the screen, because double_shows never explicitly returned anything. A function with no return implicitly hands back None, and that is exactly what explains the "unsupported operand type for NoneType" errors a few lines later: the function did its work, it simply returned nothing, and that nothing is what the code tries to multiply.
Returning several values
A calculation sometimes produces more than one useful result, like the length of a text and its uppercase version. Writing two separate functions for that would mean redoing the same work twice, which is exactly what return avoids by sending back several values at once, separated by commas, as here.
def analyse(text):
return len(text), text.upper()
length, shouted = analyse("hello")Technically, Python only ever returns one object, a tuple, but the writing stays direct on both ends: commas when writing it, matching variables when reading the result.
return a, b and return (a, b) build exactly the same tuple. The parentheses change nothing about the syntax, they only make longer expressions more comfortable to read.
Past three values this form gets hard to read, because position alone tells what each variable holds. A dictionary or a data class names the fields and removes that dependency on position.
Return or modify, pick one
A function that does both at once, handing back a result and changing what it was given, quickly becomes hard to follow: reading the call alone does not tell whether the value received is fresh or the original transformed. Python's list methods show the convention to follow: those that modify in place return None, as shown by these two close relatives.
names = ["Zoe", "Alex", "Marie"]
sorted_names = names.sort() # changes names, sorted_names is None
copy = sorted(names) # leaves names alone, copy is sortedsort() sorts the list in place and returns None, because it already did the work on the original object. sorted() leaves the original list untouched: it builds a sorted copy instead, and that copy is what it returns.
Writing my_list = my_list.sort() is one of the most common bugs among beginners: the sorted list disappears, replaced by None, and every operation that follows fails with a message that never mentions sort().
Remembering the rule avoids the mistake: when a function announces that it changes something in place, it usually returns nothing else.
Frequently asked questions
Can a function have several return statements?
Yes, and it is even recommended for ruling out edge cases early. A return on the very first line for an invalid argument saves nesting the whole body inside an if.
What does a bare return, with no value, hand back?
It hands back None, exactly like a function ending without any return. It is used to leave a function midway when there is nothing to pass on.
Can return be used outside a function?
No, that raises a SyntaxError. To stop a loop the expected statement is break, and to end a whole program it is sys.exit(). Splitting a program into functions that return values rather than blocks that print is the first habit that changes everything, and it runs through our Python course from end to end.