Building from Pieces

Building Functions with Lists


Learning Objectives

  • You can use a list parameter with familiar loop patterns.
  • You can explain how the placement of return affects a loop.
  • You can handle an empty list according to a stated requirement.
  • You can use one function’s returned value in another function.

Chapter 4 explained what happens when a function receives a list. This chapter concentrates on the algorithms inside such functions: searches, empty inputs, and functions built from other functions.

Familiar Loops Can Live Inside Functions

The selected-count pattern from Part 2 changes very little inside a function:

No files opened Select a file to edit

The function receives the list and boundary through parameters, calculates a count, and returns it. It does not decide how the result should be displayed.

A return Ends the Current Call

Chapter 3 established that return ends a function call immediately. Its position is especially important inside a loop:

def contains_negative(values):
for value in values:
if value < 0:
return True
else:
return False

This function examines only the first item. On the first iteration, one of the two returns always runs, so the call ends before the loop can reach later values.

A correct search delays the negative conclusion:

def contains_negative(values):
for value in values:
if value < 0:
return True
return False

The function may return True as soon as one negative value is found. It can return False only after the loop has checked every value without finding one.

For an empty list, the loop runs zero times and execution reaches return False. That matches the requirement: an empty list contains no negative value.

First, trace several return placements:

Then, write a function of your own for searching a list:

Search a radio log

0 / 15 points

A radio log stores received messages as strings in a list. Define contains_signal(messages, signal) to check whether the list contains a requested signal string as one complete message.

Return True if any message equals signal, and False otherwise, including when the list is empty. Compare the strings exactly: letter case and spaces matter, and a matching fragment of a message is not enough.

Use a for loop for the search. Do not print, modify messages, or use in to replace the loop.

Examples:

contains_signal(["clear", "echo", "ready"], "echo") # returns True
contains_signal(["clear", "ready"], "echo") # returns False
contains_signal([], "echo") # returns False

Submit only the function definition.

Empty Inputs Need Deliberate Behavior

Some list functions have a natural result for an empty list. A count or total can return 0, and a search can return False.

Other calculations need a design decision:

def largest_value(values):
largest = values[0]
for value in values:
if value > largest:
largest = value
return largest

This function cannot use index 0 when values is empty. Possible designs include returning a special value or requiring a nonempty input. Returning 0 only to avoid the problem would be misleading: zero is not the largest member of an empty list.

A precondition states something that must be true before a function is called. For the version above, the precondition could be “values is nonempty.” The caller must then check the empty case before calling it.

Use the stated requirement to decide whether the function accepts an empty list and what it should do with one. Chapter 9 looks more closely at writing these requirements.

Functions Can Use Other Functions

Small functions can become building blocks:

def total_values(values):
total = 0
for value in values:
total = total + value
return total
def average_value(values):
total = total_values(values)
return total / len(values)

average_value delegates summing to total_values and uses the returned number. This is function composition: one function call supplies information used by another calculation.

This particular average_value requires a nonempty list. Its caller must handle the empty case because an average does not exist for no values.

The next exercise combines several list calculations. Work on one function at a time and test ordinary cases. Test empty input where the contract accepts it; use nonempty lists for the average and summary functions. Then connect the returned results:

Summarize an expedition route

0 / 20 points

Implement four calculation functions for a route whose stage distances are stored in a list. Distances and the minimum distance are nonnegative numbers; they may include decimal fractions or zero.

  1. total_distance(distances) uses an accumulator loop and returns the total. For an empty list, it returns 0.
  2. average_distance(distances) returns the average and must use total_distance. Its precondition is that distances is nonempty: callers must not call it with an empty list.
  3. count_long_stages(distances, minimum) returns how many distances are greater than or equal to minimum. For an empty list, it returns 0.
  4. summarize_route(distances, minimum) returns a three-item list containing, in order, the total, average, and long-stage count. It must call the other three functions rather than repeat their loops. Its distances precondition is also nonempty.

For example:

summarize_route([4, 7, 3, 10], 7)

returns:

[24, 6.0, 2]

Use explicit loops for the total and count. Do not use sum, print results, or change distances. The grader calls average_distance and summarize_route only with nonempty lists. Submit only the function definitions.

The program below is incomplete - the function is missing its counting step. Add it so the program prints the correct count.

Complete a counting function with natural-language programming

0 / 5 points

This exercise uses a text editor. Edit the instructions in “Natural language program” using natural language. Write each step on its own line and indent steps that belong inside a function, loop, or condition. The editor automatically translates your program into Python; inspect “Generated Python” before submitting.

The starter defines count_long(sessions), initialises a counter, and returns it. Add one or more counting steps between the counter initialisation and the return, inside the function body. Keep the existing steps and the final function call.

The function must return how many values in sessions are strictly greater than 30, without printing inside the function. Values equal to 30 do not count. It must work for different lists and return 0 for an empty list.

The given call uses [20, 45, 15, 35, 50]. Since 45, 35, and 50 qualify, the complete program must print just one line:

3

Trace the Function Boundary

For each call, identify:

  1. which objects the argument expressions produce;
  2. which local parameter names are bound to them;
  3. where each possible return ends the call;
  4. which value is returned to the caller.

Check Your Understanding

  1. Why does count_long_words receive both a list and a minimum length as parameters?
  2. How can placing return inside a loop prevent later items from being checked?
  3. How should a function’s requirements guide its behavior when the list is empty?
  4. How can one function use a value returned by another function?

AI Study Aid

Create a chapter diagram

We're looking into to what extent AI-generated diagrams could help with studying.

Use this study aid to generate an AI-generated visual summary of the material you just studied. Each diagram style emphasizes the content in a different way, so you can choose the focus that feels most useful.

Using the diagram generator is voluntary and does not affect your course progress. We encourage you to try it out and see if it helps, but it's totally up to you! Your answers help us understand how to make better study aids in the future.

Diagrams tried: 0