Using min, max, sum
Concepts covered: Math Ops
Three built-in functions answer the first questions anyone asks about a column of numbers. sum adds every item, min returns the smallest and max returns the largest. Each takes a whole collection, walks through it and returns 1 value, replacing a loop and a running variable with a single call.
splits = (312, 298, 305, 291, 284)
print(sum(splits))
print(min(splits))
print(max(splits))
print(max(splits) - min(splits))
print(sum(splits) / len(splits))Output:
1490 284 312 28 298.0
The last 2 lines are the usual combinations: the spread between the slowest and fastest kilometre, and the average split. Division with / always produces a float, which is why the average prints as 298.0. Written out by hand, the work behind sum and min looks like this:
splits = (312, 298, 305, 291, 284)
total = 0
for s in splits:
total = total + s
fastest = splits[0]
for s in splits:
if s < fastest:
fastest = sThe 2 loops start differently. A total can start at 0 before any item is seen, while a minimum has to start from a real item, since no number is guaranteed to be larger than all of them. That difference decides what an empty collection does, further down.
Any collection, or loose arguments
All 3 accept anything you can loop over: a list, a tuple, a set or a range. min and max also accept 2 or more separate values, which suits picking the larger of 2 readings. sum takes the collection as its first argument, so sum(140, 152) raises a TypeError.
paces = [312, 298, 305]
distinct_km = {5, 10, 5, 21}
print(max(paces), min(distinct_km))
print(sum(range(1, 6)))
print(max(140, 152))
print(min(185, 210, 199))Output:
312 5 15 152 185
Strings and dictionaries compare differently
min and max work on anything that < can compare. Strings compare character by character in character-code order, where every uppercase letter sorts before every lowercase one. A dictionary passed to min or max is compared by its keys, so the answer is a key and the values play no part.
cities = ["lisbon", "Porto", "faro"]
print(min(cities))
print(max(cities))
best_km = {"ana": 21, "ben": 42, "caro": 10}
print(max(best_km))
print(min(best_km))Output:
Porto lisbon caro ana
max(best_km) returns caro because c is the latest letter among the keys, though Caro ran the shortest distance. When you want the largest number, pass the numbers. The lesson on dictionary views, later in the track, shows the direct way to hand a dictionary's values to max.
Empty collections and mixed types
An empty collection splits the 3 functions apart. sum starts at 0, finds nothing to add and returns 0. min and max have no item to start from, so they raise an error. A day with no uploads is ordinary input for a daily job, so this case reaches real code.
todays_splits = []
print(sum(todays_splits))
print(max(todays_splits, default=0))Output:
0 0
Without default, max(todays_splits) stops the program with ValueError: max() arg is an empty sequence. The default keyword argument gives min and max a value to return when the collection is empty. Choose one that cannot be mistaken for real data, or check the length first and skip the summary. default works only with a single collection; combined with loose arguments it raises a TypeError.
Mixed types fail as well. sum adds with +, so a string among the numbers raises TypeError: unsupported operand type(s) for +: 'int' and 'str'. min and max compare with <, so min([312, "298"]) raises TypeError: '<' not supported between instances of 'str' and 'int'. A split stored as text must become a number first, which the Type Conversions lesson covers.
A daily job receives a runner's splits for a day with no uploads. What does this program print?
splits = []
print(sum(splits), max(splits, default=-1))- 0 -1
- 0 0
- -1 -1
- None -1
Counting with sum
In arithmetic Python treats True as 1 and False as 0. Summing a list of comparison results therefore counts how many were true, here the kilometres run in under 5 minutes.
splits = (312, 298, 305, 291, 284)
fast = []
for s in splits:
fast.append(s < 300)
print(fast)
print(sum(fast))Output:
[False, True, False, True, True] 3
- Do
- Pass default= to min and max when the input can be empty
- Check the length before computing sum(x) / len(x)
- Pass the numbers themselves to max when you want the largest number
- Avoid
- Don't write a running-total loop where sum does the job
- Don't feed numbers stored as text into sum, min or max
- Don't expect max(some_dict) to look at the values
About this lesson
This section is part of the Collections: Beginner lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.