1. Lighthouse

Level 3 · Tag orders by size

The request

From Megan Collins, Head of Sales

“I want to see how our orders split by size. Call anything under $50 small, $50 up to under $150 medium, and $150 or more large. Can you tag this batch?”

Your goal

Define size_band(total) returning 'small' for totals below 50, 'medium' for 50 up to but not including 150, and 'large' for 150 or more. Set result to a list with the band of each value in order_totals, in the same order.

  • Store a list of 7 in resultnot done yet

Your code

Python

Loading the editor…

    ResultPress Run to see yours

    Mote checks your result

    Press Run. Each row that matches the goal becomes a firefly in your lantern.

    The lesson

    Rules belong in functions

    Bands, tiers and labels are everywhere in business data: order size, customer value tier, delivery speed, age groups. The rule itself is simple, but it gets used in many places: a report, a chart, an email segment. Put it in a function and every place uses the same boundaries.

    def size_band(total):
        if total < 50:
            return "small"
        elif total < 150:
            return "medium"
        else:
            return "large"

    Because return ends the function, the first true branch wins. That makes each condition simple: by the time Python checks total < 150, it already knows the total isn’t below 50.

    Applying it to many values

    A function that works on one value can be applied to a whole list with a comprehension:

    bands = [size_band(t) for t in order_totals]

    You can also pass the function itself, without brackets, to map:

    list(map(size_band, order_totals))

    Both give the same list. The comprehension is more common in modern Python because it reads more naturally and is easy to extend, for example [size_band(t) for t in order_totals if t > 0].

    Passing a function by name, without calling it, is an important idea. size_band is the function; size_band(62.40) is its result. pandas methods like .map() and .apply() take the function itself and call it for you on every value.

    Boundaries, again

    The edge values in this batch are deliberate: 49.99, 50.00, 149.99 and 150.00. Run your function on exactly these and compare with the brief:

    total band
    49.99 small
    50.00 medium
    149.99 medium
    150.00 large

    If 150.00 came out as medium, the second check used <= instead of <. Testing values right on the boundary is the fastest way to find that kind of bug.

    Keep functions pure

    size_band only looks at its input and returns a value. It doesn’t print, change global variables, or modify the list. Functions like this, called pure functions, are easy to test and safe to reuse. When a function needs to read some setting, pass it in as a parameter instead of reaching for a variable defined elsewhere:

    def size_band(total, small_limit=50, large_limit=150):
        ...

    Common mistakes

    • Forgetting return in one branch, so some values come back as None.
    • Ordering the checks from largest to smallest but keeping < comparisons, which sends everything to the first band.
    • Writing map(size_band(), order_totals) with brackets. That calls the function with no argument and fails.

    If you know SQL

    This function plays the role of a CASE WHEN total < 50 THEN 'small' ... END expression. In pandas you’ll often use pd.cut for numeric bands, which does the same job for a whole column.