Designing Focused Functions

Introduction: One Job, Many Steps

Welcome back to Writing Complex Python Functions! We have arrived at the fifth unit, and the pieces we collected along the way are about to come together. So far, each function has done one small thing: branched, accumulated, filtered, or copied. Real work rarely arrives in such neat portions. A single request such as "summarize these prices" quietly contains validation, filtering, a loop, and several running totals at once.

Our program for this unit ships with one function, summarize_prices(prices, min_price=0), and two calls that print:

text
kept 4, total 96.5, largest 45.0
kept 2, total 75.0, largest 45.0

That function's body runs about eighteen lines, which instinctively feels like "too long." So here is the question that guides the whole unit: How do we tell a legitimately long function from one that should be split? The answer is not line count; it is the number of jobs.

The Four Regions of a Long Function Body

Let us meet the shipped function in full, then immediately stop reading it as eighteen unrelated lines.

Python
def summarize_prices(prices, min_price=0):
    """Summarize the prices that reach min_price.

    Preconditions:
        prices contains only non-negative numbers (validation arrives in Practice 3).

    Args:
        prices: A list of non-negative numbers.
        min_price: The smallest price to include in the summary.

    Returns:
        A one-line summary string with how many prices were kept,
        their combined total, and the largest single price.
    """
    kept = 0                        # accumulators start before the loop
    total = 0.0
    largest = 0.0
    for price in prices:
        if price < min_price:
            continue                # skip this price, keep looping
        kept += 1
        total += price
        if price > largest:
            largest = price
    return ("kept " + str(kept)
            + ", total " + str(total)
            + ", largest " + str(largest))

Read from top to bottom, the body splits into exactly four regions: the docstring contract, the accumulator initializations, the loop body (skip plus updates), and the single post-loop return. Ask what the function does, and the answer is one sentence: It summarizes a list of prices. One job, four regions, many lines.

Flow diagram of the four regions in summarize_prices

This shape is a reusable template. Any "walk a list and report on it" function can be poured into it, and keeping the regions in this same order is what makes a long body skimmable for the next person who opens the file.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal