FunctionsChapter 52 of 114
Return Values
Hand a result back, return several things, and leave early.
return hands a value back
def double(n):
return n * 2
print(double(4))Output
8
return ends the function immediately. Anything after it in that path never runs:
def check(n):
return "positive" if n > 0 else "not positive"
print("never printed")
print(check(5))Output
positive
No return means None
def shout(word):
print(word.upper())
print(shout("hey"))Output
HEY None
A bare return does the same thing, and is used to leave early:
def describe(n):
if n < 0:
return
print("got", n)
describe(-1)
describe(3)Output
got 3
Returning several values
Separate them with commas. You get a tuple, and the caller usually unpacks it:
def min_max(numbers):
return min(numbers), max(numbers)
low, high = min_max([3, 1, 4])
print(low, high)
print(min_max([3, 1, 4]))Output
1 4 (1, 4)
Past two or three values, a dictionary or a small class reads better than a tuple nobody can remember the order of.
def stats(numbers):
return {"count": len(numbers), "total": sum(numbers)}
result = stats([1, 2, 3])
print(result["total"])Output
6
Returning early
Handling the awkward cases first and returning keeps the main path unindented:
def price_for(age):
if age < 0:
return None
if age < 16:
return 0
if age >= 65:
return 5
return 12
for age in [-1, 10, 30, 70]:
print(age, price_for(age))Output
-1 None 10 0 30 12 70 5
The alternative, one nested if/else per case, indents further with every rule and is harder to change.
Every path should return the same kind of thing
A function that sometimes returns a number and sometimes a string forces every caller to check:
def parse(text):
try:
return int(text)
except ValueError:
return None
for text in ["10", "ten"]:
value = parse(text)
if value is None:
print(text, "could not be read")
else:
print(text, "->", value + 1)Output
10 -> 11 ten could not be read
Returning None for "no answer" is idiomatic. Just be consistent, and say so in the docstring.
Returning a function
A function can return another function, which is how decorators and small factories work:
def multiplier(factor):
def multiply(n):
return n * factor
return multiply
triple = multiplier(3)
print(triple(5))Output
15
multiply remembers factor after multiplier has finished. That captured variable is called a closure, and the scope chapter comes back to it.
Test yourself
2 questionsWhat does a function return when it has no return statement?
Show the answer
None — A bare return does the same thing, and is the idiomatic way to leave early.
What do you get from 'return min(numbers), max(numbers)'?
Show the answer
A tuple of both — The comma makes the tuple, and the caller usually unpacks it into two names.
Scope
Where a name is visible, and the order Python searches.