A game club has a whole row of scores to organize, compare, and improve. Your challenge is to keep related values together, visit every value, and build useful new collections without losing track of the original data.
By Lesson 3, you will turn a score list into filtered results and running totals with reusable functions.
You will learn
- Make a list, read or change an item by position, and add or remove items.
- Visit list items in a loop and take a slice of a list.
- Sort a list and find its largest or smallest item by checking items in order.
- Build a new list containing only items that pass a test.
Lesson 1: Build and Read
Start the score board
A list keeps several values in order. Square brackets make a list literal, and commas separate its items.
scores = [3, 1, 2]
print(scores)
Output
[3, 1, 2]Notice
The three scores stay together in their written order.
An index reaches one position: index 0 is the first position.
print(scores[0])
Output
3Notice
Index 0 selects 3, not the whole list. A negative index counts from the end, as it did for strings in Unit 09.
print(scores[-1])
Output
2Notice
Index -1 selects the last score, 2. Use len to count the items.
print(len(scores))
Output
3Notice
There are three items. Assign through an index to change one existing item.
scores[1] = 5
print(scores)
Output
[3, 5, 2]Notice
The second score changes, and the list is now [3, 5, 2]. A function can take a list and return its first item.
def first_score(scores):
return scores[0]
print(first_score(scores))
Output
3Notice
first_score(scores) returns 3. It expects a nonempty list, because an empty list has no position 0.
Loop over the values
When you need each value but not its position, loop directly over the list. The loop below visits one score at a time. len(scores) gives the number of items, and sum(scores) gives their total.
def total_with_values(scores):
total = 0
for score in scores:
total = total + score
return total
def score_report(scores):
return f"{len(scores)} scores total {sum(scores)}"
print(total_with_values([4, 7, 5]))
print(score_report([4, 7, 5]))
Output
16
3 scores total 16The calls return 16 and the report 3 scores total 16. The hand-written loop exposes the running total, while sum performs the same common job in one call. A direct value loop is the clearest choice when the positions do not matter.
Build a new list with append
The method call some_list.append(value) adds one item at the end of a list. Start with an empty list when the answer will be built one item at a time. Each loop trip calculates one new value and appends it.
def double_values(numbers):
doubled = []
for number in numbers:
doubled.append(number * 2)
return doubled
print(double_values([2, 5, 8]))
print(double_values([-3, 0, 4]))
Output
[4, 10, 16]
[-6, 0, 8]The calls return [4, 10, 16] and [-6, 0, 8]. The input list supplies the values; the empty doubled list grows with one append call per trip. The function returns a new list.
Change a list in place
insert(0, value) places a value before the current first item.
line = [4, 7, 9]
line.insert(0, 2)
print(line)
Output
[2, 4, 7, 9]Notice
The line is now [2, 4, 7, 9]. pop() removes and returns the last item.
last = line.pop()
print(last, line)
Output
9 [2, 4, 7]Notice
last is 9; the line now ends at 7. Give pop an index to remove a different position.
first = line.pop(0)
print(first, line)
Output
2 [4, 7]Notice
first is 2; the line is [4, 7]. remove(value) removes the first matching value.
line.append(4)
line.remove(4)
print(line)
Output
[7, 4]Notice
Only the first 4 was removed, leaving [7, 4]. index(value) finds the position of the first match.
print(line.index(4))
Output
1Notice
The remaining 4 is at index 1. remove and index raise ValueError for a missing value, so check if value in line: first.
Loop over the positions
Sometimes a calculation needs both the current item and another position. range(len(scores)) supplies every valid index from 0 through one less than the list length. To compare each score with the previous score, begin at index 1.
def score_changes(scores):
changes = []
for i in range(1, len(scores)):
change = scores[i] - scores[i - 1]
changes.append(change)
return changes
print(score_changes([8, 11, 10, 15]))
print(score_changes([6]))
Output
[3, -1, 5]
[]The calls return [3, -1, 5] and []. The index loop is useful because scores[i] and scores[i - 1] reach neighboring positions. A one-item list has no pair to compare, so its result stays empty.
Slices and list equality
A slice selects a section into a new list; the end index is excluded.
print(scores[1:3])
Output
[5, 2]Notice
The result is [5, 2]; scores is unchanged. A step of -1 makes a new list in reverse order.
print(scores[::-1])
print(scores)
Output
[2, 5, 3]
[3, 5, 2]Notice
The reversed list is [2, 5, 3], while scores remains [3, 5, 2]. Two lists compare equal when their items match in the same order.
print([1, 2] == [1, 2], [1, 2] == [2, 1])
Output
True FalseNotice
Python prints True False; changing the order changes the list.
Read several numbers on one line
split() separates one line at its spaces into a list of strings.
line = "7 3 8"
parts = line.split()
print(parts)
Output
['7', '3', '8']Notice
parts is ["7", "3", "8"]; its items are strings. Convert individual pieces before doing arithmetic.
print(int(parts[0]) + int(parts[1]))
Output
10Notice
The first two numbers add to 10. To convert every piece, append each converted value in a loop.
numbers = []
for part in parts:
numbers.append(int(part))
print(numbers)
Output
[7, 3, 8]Notice
numbers holds [7, 3, 8] as integers. join can put a separator between the string pieces in a list.
print("-".join(parts))
Output
7-3-8Notice
The string result is 7-3-8. Here join receives a list of strings; Unit 09 joined letters from one string. A real program can read that line with input().
Try it yourself
parts = input("Numbers: ").split()
numbers = []
for part in parts:
numbers.append(int(part))
print(sum(numbers))
Notice
This input cell waits for a line such as 7 3 8 and prints its total. Another common format puts the count first, followed by one number per line.
Try it yourself
n = int(input("How many numbers? "))
numbers = []
for i in range(n):
numbers.append(int(input("Number: ")))
print(numbers)
Notice
The second input cell reads exactly n values into one list.
Lesson 2: Order and Choose
A tournament organizer needs a low-to-high score board and the position of the winning score. Sorting can order the values, but choosing a position requires a careful index loop.
Notice
Notice: sort changes a list and returns None
The list method sort rearranges the existing list in place. Its returned value is None, which means it does not hand back a useful new list. Predict the two printed lines.
nums = [9, 2, 6]
scores = nums.sort()
print(nums)
print(scores)
Output
[2, 6, 9]
NonePython prints [2, 6, 9] and then None. The call changed nums, but scores = nums.sort() saved the method's missing return value. This is the None trap: do not assign the result of sort when you want the changed list.
Sort in place when changing the input is the job
Call sort as its own statement, then return the now-ordered list if the caller needs that value.
def order_in_place(scores):
scores.sort()
return scores
print(order_in_place([12, 5, 8]))
print(order_in_place([-2, -9, -4]))
Output
[5, 8, 12]
[-9, -4, -2]The calls return [5, 8, 12] and [-9, -4, -2]. This function deliberately changes the list it receives. Its name says that in-place change is part of the job.
Use sorted when the original order must stay
The built-in function sorted(scores) returns a new ordered list. It leaves the original list in its old order.
def ordered_copy(scores):
return sorted(scores)
original_scores = [14, 7, 11]
new_order = ordered_copy(original_scores)
print(original_scores)
print(new_order)
Output
[14, 7, 11]
[7, 11, 14]Python prints [14, 7, 11] and [7, 11, 14]. Choose sort for an intentional in-place change and sorted for a separate ordered result.
A real program can read one line of numbers, convert every piece, and print the ordered copy.
Try it yourself
parts = input("Numbers: ").split()
numbers = []
for part in parts:
numbers.append(int(part))
print(sorted(numbers))
Notice
sorted returns a new list in low-to-high order.
Built-in list calculations
For a list with at least one number, min returns its smallest item and max returns its largest item. sum returns the total. These built-ins answer common value questions, but they do not tell you the position of a winning value.
def number_summary(numbers):
return [min(numbers), max(numbers), sum(numbers)]
print(number_summary([7, 2, 10, 4]))
print(number_summary([-8, -3, -12]))
Output
[2, 10, 23]
[-12, -3, -23]The calls return [2, 10, 23] and [-12, -3, -23]. The second call is a reminder that the largest negative number is still negative.
Find an extreme by hand
A hand-written extreme loop remembers the best value seen so far. This function assumes the list has at least one item, so numbers[0] is a real starting value. Never start best at 0: a list of negative numbers might not contain any value as large as 0.
def find_largest(numbers):
best = numbers[0]
for number in numbers:
if number > best:
best = number
return best
print(find_largest([5, 12, 9]))
print(find_largest([-11, -4, -7]))
Output
12
-4The calls return 12 and -4. Seeding from the first item makes the loop correct for negative values too. The built-in max is shorter when only the value matters; the hand-written loop can be adapted when the position matters.
Find the position of the maximum
An argmax is the position of a largest value. Remember a position rather than the value itself, then compare through list indexes. This function assumes the list has at least one item.
def position_of_largest(numbers):
best_position = 0
for i in range(1, len(numbers)):
if numbers[i] > numbers[best_position]:
best_position = i
return best_position
print(position_of_largest([13, 21, 18]))
print(position_of_largest([-2, -7, -1]))
Output
1
2The calls return 1 and 2. Because the comparison uses > rather than >=, equal largest values leave the earliest winning position in place.
Apply argmax to words
The same position loop can compare calculated qualities instead of number values. To find the longest word, compare the lengths of the words at two positions. The list must have at least one item.
def position_of_longest(words):
best_position = 0
for i in range(1, len(words)):
if len(words[i]) > len(words[best_position]):
best_position = i
return best_position
print(position_of_longest(["ant", "butterfly", "moth"]))
print(position_of_longest(["red", "blue", "gold"]))
Output
1
1The calls return 1 and 1. In the second list, blue and gold tie at length 4, so the earlier position wins. This is why an index loop can solve more than the built-in value questions.
Lesson 3: Filter and Combine
A coach needs a clean list of qualifying scores and a progress line that shows the total after every round. Both jobs build a new list one decision at a time.
Count values that pass a test
A counter can record how many items pass a condition. It starts at 0 and increases only when the current score reaches the minimum.
def count_qualifiers(scores, minimum):
count = 0
for score in scores:
if score >= minimum:
count = count + 1
return count
print(count_qualifiers([8, 13, 11, 6], 10))
print(count_qualifiers([4, 5, 3], 7))
Output
2
0The calls return 2 and 0. Counting answers how many values pass; filtering keeps the passing values themselves.
Filter into a new list
To filter, start with an empty result list. Loop over the input, test each item, and call append only inside the if body. This example also practices membership with in.
On a list, in tests whole-item list membership — “is this value one of the items?” — unlike Unit 09, where in tested character or substring membership inside a string.
def keep_allowed(values, allowed):
kept = []
for value in values:
if value in allowed:
kept.append(value)
return kept
print(keep_allowed([4, 9, 2, 9, 7], [2, 4, 7]))
print(keep_allowed([5, 6], [1, 2, 3]))
Output
[4, 2, 7]
[]The calls return [4, 2, 7] and []. The result keeps the input order and includes only values that belong to allowed. Building with an explicit loop makes every filtering decision visible.
Build prefix sums
A prefix sum is the total so far after each item. Update the running total first, then append that total once per loop trip.
def prefix_sums(numbers):
totals = []
running_total = 0
for number in numbers:
running_total = running_total + number
totals.append(running_total)
return totals
print(prefix_sums([3, 5, 2, 6]))
print(prefix_sums([-2, 7, -1]))
Output
[3, 8, 10, 16]
[-2, 5, 4]The calls return [3, 8, 10, 16] and [-2, 5, 4]. Each returned item answers, “What is the total through this position?”
Lists inside lists: a grid
Each inner list can hold one row of a grid. Read a complete row with one index.
grid = [[1, 1, 0], [0, 1, 1]]
print(grid[1])
Output
[0, 1, 1]Notice
Row 1 is [0, 1, 1]. A second index selects a column inside that row.
print(grid[1][0])
Output
0Notice
Row 1, column 0 holds 0. Nested loops can turn each numeric row into a text row.
rows = []
for grid_row in grid:
row_text = ""
for value in grid_row:
if value == 1:
row_text = row_text + "#"
else:
row_text = row_text + "."
rows.append(row_text)
print("\n".join(rows))
Output
##.
.##Notice
The picture prints as ##. and .## on separate lines. "\n".join(rows) makes one string for the whole picture. A board can also store each row as a string.
board = ["#..", ".#.", "..#"]
print(board[2][2])
Output
#Notice
The bottom-right cell is #. To read a board, read its row count, then one row string per line.
Try it yourself
row_count = int(input("Rows: "))
board = []
for i in range(row_count):
board.append(input("Row: "))
print(board)
Notice
This input cell builds a list of row strings, ready for board[row][column].
Put it together: keep above-average scores
This function assumes the list has at least one item. First calculate the average with sum(scores) / len(scores). Then filter every score that is strictly greater than that average into a new list.
def above_average(scores):
average = sum(scores) / len(scores)
kept = []
for score in scores:
if score > average:
kept.append(score)
return kept
print(above_average([10, 16, 12, 18]))
print(above_average([7, 7, 7]))
Output
[16, 18]
[]The first average is 14.0, so the function returns [16, 18]. The second average is 7.0, so no score is strictly above it and the function returns [].
Put it together: lists keep ordered data, value loops visit items, index loops connect values to positions, and append builds new results. Sorting, finding an extreme, filtering, and prefix sums are different questions built from those same tools.
Recap
[3, 1, 2]keeps three values in order;scores[0]reads the first one.appendgrows a list, while a loop can visit each item or its position.scores.sort()changes the list;sorted(scores)makes an ordered copy.- To find an extreme, keep the best value or position seen so far.
- To filter, test each item and append only the ones you want to a new list.
You can now organize the game club's scores and build a list of qualifying scores.