Processing Lists with Functions

Introduction: One Parameter, A Whole List

Welcome back to Writing Complex Python Functions! We are now in the third unit of this course. In the previous unit, our loops worked on data that the function produced on its own with range, or pulled apart from a string with text.split(). This time, the data arrives from outside: the caller hands over an entire collection through a single parameter.

Our program ships with two functions. average(numbers) takes a list and gives back one number; above_average(numbers) takes a list and gives back a different list. Running it prints exactly this:

text
Average: 25.0
Above average: [45, 33, 27]
Original list untouched: [12, 45, 33, 8, 27]

Two questions guide the whole unit: What comes back: one value or a new list? and Does the caller's original list survive the call? That third line is our answer to the second question.

A List Parameter Is Just a Parameter

There is nothing special about a function that accepts a list. The def line looks exactly like the ones we wrote in earlier courses; the only difference is what the caller chooses to pass in.

Python
def average(numbers):
    """Return the mean of a list of numbers; we define empty input to return 0.0."""
    if not numbers:
        return 0.0
    return sum(numbers) / len(numbers)


readings = [12, 45, 33, 8, 27]
print("Average:", average(readings))

The name numbers binds to whatever list the caller supplies, just as any parameter binds to its argument. Once bound, the body can use every list tool Python offers on it: len(numbers), sum(numbers), or a for loop. Tracing average(readings): sum([12, 45, 33, 8, 27]) is 125, len(...) is 5, and 125 / 5 is 25.0. Note that / always produces a float, which is exactly why the printed line ends in .0:

text
Average: 25.0

Guarding the Empty List

Look again at the first statement in the body. It is a guard clause, the same tool we used in Unit 1 to reject invalid input before doing real work.

Python
    if not numbers:
        return 0.0
    return sum(numbers) / len(numbers)   # safe: the list has at least one value

Mathematically, the mean of an empty list is undefined. Without a guard, average([]) would also crash: sum([]) is 0, len([]) is 0, and 0 / 0 raises ZeroDivisionError. For this course we define empty input to return 0.0—a chosen empty-input policy, not the true mathematical mean. That policy keeps the program running and lets every line below the guard assume a nonempty list.

Flowchart showing how the empty-list guard prevents division by zero

if not numbers is the idiomatic way to ask, "Is this list empty?" in Python: an empty list is falsy, so not numbers is True precisely when there is nothing to work with. Writing if len(numbers) == 0 behaves the same way, but Python programmers expect the shorter form.

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