Fruitful Functions in Python
A fruitful function in Python is one that uses return to hand back a value the caller can store or use, unlike a void function which returns None. Build them incrementally, one small tested step at a time.
Every void function you've written so far does something, prints something, moves something — but when you ask it for a value, it hands you back None. Fruitful functions in Python are different: they actually return something useful, something you can store, calculate with, and build on.
This page covers the return statement, a safe way to build fruitful functions incrementally without breaking them, and boolean functions that answer yes-or-no questions. It follows on from Functions in Python: Definition and How They Work.
What you will learn
- How
returnhands a value back to the caller - Why unreachable code after a
returnis called dead code - A subtle bug: forgetting to return on every possible path
- Incremental development — building functions in small, testable steps
- Writing boolean functions that read like plain English
Return values: making functions give back
The difference between a void and a fruitful function comes down to one thing — a return statement carrying an expression:
def area(radius):
return math.pi * radius**2When Python hits this line, it immediately exits the function and hands back the computed value to whoever called it. You can then store that value, print it, or use it inside another expression:
a = area(5) # store it
print(area(5)) # print it
x = area(5) * 2 # use it in an expressionSometimes keeping a temporary variable makes things easier to read and debug — both versions below work identically:
def area(radius):
temp = math.pi * radius**2
return tempMultiple return statements and dead code
You can have multiple return statements — one per branch of a conditional:
def absolute_value(x):
if x < 0:
return -x
else:
return xThe moment any return executes, the function stops — nothing after it runs. Code that can never be reached is called dead code; it sits there silently doing nothing, usually a sign something is structured incorrectly.
Incremental development: building code without breaking it
As functions get more complex, bugs become harder to find — especially if you write everything at once and only test at the end. Incremental development solves this by building in small, testable steps. Say you want to compute the distance between two points using the Pythagorean theorem: distance = sqrt((x2-x1)² + (y2-y1)²)
Step 1 — start with a skeleton that runs:
def distance(x1, y1, x2, y2):
return 0.0It returns the wrong answer, but it runs without errors — you have confirmed the structure is correct.
Step 2 — add computation, verify with print statements:
def distance(x1, y1, x2, y2):
dx = x2 - x1
dy = y2 - y1
print('dx is', dx)
print('dy is', dy)
return 0.0Test with distance(1, 2, 4, 6) — you should see dx is 3 and dy is 4. If you do, the inputs are correct and the first step works.
Step 3 — add the next piece:
def distance(x1, y1, x2, y2):
dx = x2 - x1
dy = y2 - y1
dsquared = dx**2 + dy**2
print('dsquared is:', dsquared)
return 0.0Expected output: dsquared is: 25. If correct, move on.
Step 4 — complete the function:
def distance(x1, y1, x2, y2):
dx = x2 - x1
dy = y2 - y1
dsquared = dx**2 + dy**2
result = math.sqrt(dsquared)
return resultOnce it works, remove all the print statements. Those temporary print lines are called scaffolding — useful while building, removed from the final product. The principle is simple: at any point, if something breaks, you know exactly which two or three lines could be responsible — you never have to hunt through fifty lines of untested code.
Boolean functions: functions that answer yes or no
Functions can return booleans too, and this turns out to be extremely useful for packaging up conditions that would otherwise clutter your code:
def is_divisible(x, y):
if x % y == 0:
return True
else:
return FalseBut since x % y == 0 is already a boolean expression, you can simplify this considerably:
def is_divisible(x, y):
return x % y == 0Both do the same thing — the second is just cleaner. Use boolean functions in conditionals naturally:
if is_divisible(x, y):
print('x is divisible by y')Notice — you do not need if is_divisible(x, y) == True. The function already returns a boolean, so comparing it to True is redundant; just use it directly.
A first taste of recursion
Fruitful functions unlock something powerful: a function can call itself. This is called recursion, and it's how you compute things like factorial (n! = n × (n-1)!) — each call solves a smaller version of the same problem until it hits a base case. The full walkthrough, including the "leap of faith" mental model and guarding against bad input, lives in Recursion in Python.
Common mistakes
- Missing a
returnon one branch, so the function silently returnsNonein that case - Writing code after a
returnstatement that can never execute (dead code) - Comparing a boolean function's result to
Trueinstead of using it directly - Skipping incremental development on a complex function and debugging fifty lines at once
Common questions
What is a fruitful function in Python?
A fruitful function is one that uses the return statement to hand back a value the caller can store, print, or use in an expression, as opposed to a void function which returns None.
What happens if a function doesn't hit a return statement on every path?
If a possible execution path through the function never reaches a return statement, Python silently returns None for that case — no error is raised, which can hide bugs.
What is dead code in Python?
Dead code is code that can never execute, most commonly statements placed after a return statement in the same block. Since return exits the function immediately, anything after it is unreachable.
What is incremental development in programming?
Incremental development means building a function in small, testable steps — starting with a skeleton that runs, adding one piece of logic at a time, verifying with print statements, then removing that scaffolding once the function works.
Do I need to compare a boolean function's result to True?
No. If a function already returns True or False, use it directly in an if statement, like if is_divisible(x, y):, instead of writing if is_divisible(x, y) == True:.
Explore
Related topics
Keep going — these sit next to this concept in a real learning path.
Functions in Python: Definition and How They Work
def, parameters, and calling functions from the start.
Functions in Python in Depth: The Complete Guide
Default args, *args/**kwargs, lambdas, and scope — all in one.
Built-in Functions in Python
type(), len(), range(), and the functions always available.
Python course hub
All free Python explainers and the path into Agentic practice.
Libraries and Modules in Python
import, from ... import, and the math/random modules.
Recursion in Python
Base cases, stack frames, factorial, and Fibonacci.