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


