Finding Extremes: Maximum and Minimum Values in Loops
An accumulator is a variable that starts with an initial value before a loop, gets updated on each iteration, and holds the final result when the loop ends.
Why Running Results Matter
A loop examines one item at a time, but many tasks require information from all the items examined so far. You might count the items, add their values, or keep the largest or smallest value encountered. An accumulator is the variable that makes this possible: it starts before the loop, changes during each iteration, and holds the final result when the loop ends.
Finding an extreme value appears in many data tasks. A weather application may find the highest temperature recorded during a week, a sales system may identify the lowest-priced item, and a fitness tracker may find a maximum heart rate during a workout.
The central question is: what should the variable represent after each iteration? A counter represents how many items have been seen, a total represents the sum of the items seen, and an extreme variable represents the largest or smallest item seen so far.
The Accumulator Pattern
Every accumulator loop has three parts. First, initialize the accumulator before the loop. Second, update it inside the loop on every iteration. Third, use its value after the loop finishes. The update must match the question being answered. Counting adds 1 for every item, while summing adds the current item's actual value.
values = [4, 9, 2] count = 0 total = 0 for value in values: count += 1 total += value print(count) print(total)
| Task | Initial value | Update inside the loop | Meaning after each iteration |
|---|---|---|---|
| Counting | 0 | count += 1 | Number of items seen so far |
| Summing | 0 | total += value | Sum of values seen so far |
The update determines what the accumulator represents.
Tracing Each Iteration
Tracing a Running Total
Find the count and total for the values 4, 9, and 2.
Before the loop: count is 0 and total is 0. No items have been processed.
After 4: count becomes 1. total becomes 0 + 4, which is 4.
After 9: count becomes 2. total becomes 4 + 9, which is 13.
After 2: count becomes 3. total becomes 13 + 2, which is 15.
The final count is 3 and the final total is 15.
A useful trace records the accumulator after each item. If a total suddenly returns to zero, or if a counter changes by more than 1, the trace exposes the problem. The accumulator should not be reset inside the loop; it should carry its previous value into the next iteration.
Initializing the accumulator inside the loop
The previous total is discarded on every iteration, so the variable does not accumulate all the values.
Fix:
Set total = 0 before the loop, then update total inside the loop.Adding 1 when the task is summing
This counts iterations instead of adding the current item's value.
Fix:
Use total += value for a numeric total.Using the item value when the task is counting
The result depends on the values rather than on how many items were processed.
Fix:
Use count += 1 for counting.
The Largest-So-Far Pattern
To find a maximum, maintain a variable that represents the largest value seen so far. For each new item, update that variable only when the new item is strictly larger. The condition has two parts: largest is None handles the first item, and value > largest handles later comparisons.
12In the example, the first item becomes the initial largest value because largest is None. The next item, 3, does not replace 7. The value 12 does replace it because 12 is larger. The final value, 5, leaves the result unchanged. The variable always describes the largest value encountered up to that point.
The Smallest-So-Far Pattern
The minimum pattern has the same structure as the maximum pattern. Initialize smallest to None, then replace it when the current item is strictly smaller. The only comparison change is from the greater-than operator to the less-than operator: if smallest is None or value < smallest.
3Tracing the Minimum
Find the smallest value in the sequence 8, 2, 6, and 1.
Before the loop: smallest is None, so no value has been selected yet.
After 8: Because smallest is None, 8 becomes the current smallest value.
After 2: 2 is smaller than 8, so smallest becomes 2.
After 6: 6 is not smaller than 2, so smallest remains 2.
After 1: 1 is smaller than 2, so smallest becomes 1.
The final smallest value is 1.
Why None Starts the Search
None marks the extreme variable as empty before any item has been examined. On the first iteration, the None part of the condition is true, so the first item becomes the initial largest or smallest value. Later iterations can use ordinary numeric comparisons.
Built-In Functions in Practice
| Manual pattern | Built-in function | Use in practical code |
|---|---|---|
| Counting loop | len(values) | Prefer len() for the number of items. |
| Summing loop | sum(values) | Prefer sum() for the total of numeric items. |
| Maximum loop | max(values) | Prefer max() for the largest value. |
| Minimum loop | min(values) | Prefer min() for the smallest value. |
4
27
12
3The built-in functions produce the same kinds of results as the manual patterns while being shorter and clearer for these specific tasks. The manual loops are still worth learning because they expose the algorithm, support tracing and debugging, and transfer to situations where a ready-made function does not provide the exact operation you need.
Practice the Patterns
Write a loop that examines values = [11, 4, 18, 6]. Keep track of the largest value and the smallest value. Before running the code, write down the value of each variable after every iteration.
Hints
- Initialize largest and smallest to None before the loop.
- Use value > largest for the maximum comparison.
- Use value < smallest for the minimum comparison.
For the same list, decide which version is clearer in practical Python code: a manual counting loop or len(values), a manual summing loop or sum(values), and a manual extreme-finding loop or max(values) and min(values). Explain why the manual versions are still useful to understand.
Hints
- Use the built-in functions for these basic operations in real code.
- Use manual loops to study the accumulator and comparison patterns.
- Check that your trace never resets the accumulator inside the loop.
Using the wrong comparison operator
The loop may keep smaller values instead of larger ones.
Fix:
Use > for largest and < for smallest.Updating the extreme on every iteration
The variable becomes the most recently examined item, not the largest item seen so far.
Fix:
Update only when the new value is strictly more extreme.Forgetting the None initialization case
The first item needs a way to become the initial extreme before an ordinary comparison can be made.
Fix:
Use largest is None or value > largest, and use the analogous condition for smallest.
Pattern Summary
- Initialize an accumulator before the loop and update it inside the loop without resetting it.
- Counting adds 1 for every item, while summing adds the current item's value.
- For a maximum, keep the largest value seen so far and update with a strictly larger item.
- For a minimum, keep the smallest value seen so far and update with a strictly smaller item.
- Use None to let the first item establish the initial extreme, and prefer len(), sum(), max(), and min() for these basic operations in practical Python code.
Key Takeaways
- An accumulator persists across iterations and holds a result when the loop ends.
- Counting and summing use different updates: increment by 1 for counting and add the item for summing.
- Maximum and minimum loops compare each new item with the current extreme.
- None allows the first item to become the initial maximum or minimum.
- Use Python's built-in functions for straightforward counting, summing, and extreme-finding tasks.