SythraOpen app

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.

Sythra

8 min read

XLinkedIn
Fruitful Functions in Python — cover illustration

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 return hands a value back to the caller
  • Why unreachable code after a return is 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**2

When 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 expression

Sometimes 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 temp

Multiple 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 x

The 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.0

It 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.0

Test 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.0

Expected 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 result

Once 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 False

But since x % y == 0 is already a boolean expression, you can simplify this considerably:

def is_divisible(x, y):
    return x % y == 0

Both 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 return on one branch, so the function silently returns None in that case
  • Writing code after a return statement that can never execute (dead code)
  • Comparing a boolean function's result to True instead 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.

Browse all python explainers →