---
title: Fruitful Functions in Python
source: https://app.sythra.ai/learn/python/fruitful-functions-python
topic: Python
updated: 2026-08-12
publisher: Sythra (https://app.sythra.ai)
---

# 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.

_Source: [https://app.sythra.ai/learn/python/fruitful-functions-python](https://app.sythra.ai/learn/python/fruitful-functions-python) — free to read on Sythra._

## Key points

- return exits a function immediately and hands back a value
- Code after a return statement never runs — it's dead code
- Missing a return on one branch silently returns None
- Incremental development: build and test in small verifiable steps, then remove scaffolding prints
- Boolean functions (is_divisible, is_between) can be used directly in if statements

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](/learn/python/functions-in-python).

## 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:

```python
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:

```python
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:

```python
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:

```python
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.

> **A trap worth knowing:** 

## 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:**

```python
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:**

```python
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:**

```python
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:**

```python
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:

```python
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:

```python
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:

```python
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.

> **Naming convention:** 

## 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](/learn/python/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

> **Practice with Sythra:**  [Practice with AI tutor](https://app.sythra.ai/pricing)

## FAQ

### 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:.

## Related

- [Functions in Python: Definition and How They Work](https://app.sythra.ai/learn/python/functions-in-python) — def, parameters, and calling functions from the start.
- [Functions in Python in Depth: The Complete Guide](https://app.sythra.ai/learn/python/python-functions-in-depth) — Default args, *args/**kwargs, lambdas, and scope — all in one.
- [Built-in Functions in Python](https://app.sythra.ai/learn/python/built-in-functions-python) — type(), len(), range(), and the functions always available.
- [Python course hub](https://app.sythra.ai/learn/python) — All free Python explainers and the path into Agentic practice.
- [Libraries and Modules in Python](https://app.sythra.ai/learn/python/libraries-and-modules-python) — import, from ... import, and the math/random modules.
- [Recursion in Python](https://app.sythra.ai/learn/python/recursion-in-python) — Base cases, stack frames, factorial, and Fibonacci.

---

Written by Sythra — Learn machine learning by building. Practice this topic with Sythra's AI tutor: https://app.sythra.ai/pricing
