Lists
Problem
Thirty grades
A teacher writes a program for the test scores. For five students they make five variables:
score1 = 62score2 = 85score3 = 47score4 = 91score5 = 78total = score1 + score2 + score3 + score4 + score5print(total)363But the class has thirty students. Thirty variables, thirty terms to add. And the highest score needs twenty-nine more comparisons. The loop from the last lesson does not help: it cannot go through score1, score2, score3, because those are separate names. We need many values under one name.
The idea
A list: a row of boxes
A list is a row of values under one name. Each value, an element of the list, has a number: its index. Indexes start at 0. In Java and C# the same thing is called an array.
scores = [62, 85, 47, 91, 78]print(scores[0])print(scores[4])print(len(scores))scores[2] = 50print(scores[2])6278550- The values go in square brackets
[ ], separated by commas. You don't write a type. You can mix numbers and text in one list, but usually all the elements are of one kind.
scores[0]is the first element,scores[4]the fifth. The last index is always 1 less than the count.len(scores)is the number of elements. Here it is 5.scores[2] = 50changes one element. The others stay the same.
If you don't know the values yet, but you know how many there are, you multiply a list holding one zero by the count:
booked = [0] * 3booked[1] = 2print(booked)[0, 2, 0]Unlike arrays in Java and C#, a list grows. append adds an element at the end:
scores = [62, 85]scores.append(47)print(scores)print(len(scores))[62, 85, 47]3print of a whole list shows its elements in [ ]. That is handy for checking, but for the program's output you usually print the elements yourself.
More precisely, if you are curious
- A negative index counts from the back:
scores[-1]is the last element,scores[-2]the one before it.
scores = [62, 85, 47, 91, 78]print(scores[-1])print(scores[-2])7891Try it
Which is which?
What will the program print?
prices = [12, 7, 30, 5]print(prices[1] + prices[3])We count from 0: prices[1] is 7 (the second), prices[3] is 5 (the fourth). 7 + 5 = 12. If you count from 1, you will take 12 and 30.
The idea
A loop through the list
Now the loop does help. The counter i becomes the index: it goes from 0 to the last one and on every round takes scores[i].
scores = [62, 85, 47, 91, 78]total = 0for i in range(len(scores)): total += scores[i]print(f"Sum: {total}")print(f"Average: {total / len(scores)}")Sum: 363Average: 72.6The counter goes through range(len(scores)): from 0 to len(scores) - 1, exactly the indexes. If you add all thirty grades in [ ], the loop does not change. This is called traversing the list.
/ in Python always gives a decimal number, so the average comes out as 72.6 with nothing extra. Integer division is //.
More precisely, if you are curious
Python also has ready-made functions for this: sum(scores) is the sum, max(scores) and min(scores) are the biggest and the smallest. Here we write them ourselves, so you can see how they work. That is also why the variable is total and not sum: this way the name sum stays free for the function.
scores = [62, 85, 47, 91, 78]print(sum(scores), max(scores), min(scores))363 91 47See it
The highest score
How do you find the biggest number? You remember the biggest one so far and replace it as soon as you see a bigger one.
scores = [62, 85, 47, 91, 78]highest = scores[0]for i in range(1, len(scores)): if scores[i] > highest: highest = scores[i]print(highest) # 91Step by step, in words
- Five scores, side by side. The numbers below are the indexes: from 0 to 4.
- highest starts from the first one: scores[0] is 62.
- i = 1: 85 > 62, so highest becomes 85.
- i = 2: 47 is not bigger than 85. Nothing changes.
- i = 3: 91 > 85, so highest becomes 91.
- i = 4: 78 < 91. range(1, len(scores)) is used up: the stop value 5 is not included, and the loop stops.
- The highest score is 91.
highest starts from the first element, not from 0. If all the scores were negative, 0 would "win" without being in the list. That is also why the loop starts from range(1, …): the first one is already in highest.
Try it
Find the bug
The program should print the sum 363. Instead it stops with an error:
IndexError: list index out of rangeWhich line has the bug?
Pick the line with the bug.
range(1, len(scores) + 1) counts from 1 to 5, like the students' numbers. But the indexes of a list with 5 elements go from 0 to 4: there is no scores[5], and the program stops with IndexError. This is called going outside the list. And scores[0] would have been skipped. The fix is range(len(scores)).The idea
for … in: for every element
When you need only the values and not the indexes, there is a shorter loop. How many students passed the exam (60 points or more)?
scores = [62, 85, 47, 91, 78]passed = 0for score in scores: if score >= 60: passed += 1print(f"Passed the exam: {passed}")Passed the exam: 4It reads "for each score in scores". This is the same for, except it goes straight through the elements of the list instead of the numbers from range. In Java the same thing is called for-each. There is no counter and no index, so you cannot go outside the list.
There is a limit too: you don't know which index you are at, and you cannot change the element.
More precisely, if you are curious
- If you write
score = 0in the body, you change only the variablescore. The list stays the same, and Python does not stop you:
scores = [62, 85, 47]for score in scores: score = 0print(scores)[62, 85, 47]- To change elements, or when you need the index (for example for the neighbor
scores[i + 1]), use a regularfor.
Try it
Two names, one list
What will the program print?
prices = [10, 20, 30]sale = pricessale[0] = 5print(prices[0])b = a and then b = 5 does not change a. With a list, sale = prices does not make a new list, it gives a second name to the same one. That is why a change through sale also shows through prices. Why this is so, you will learn in the module "Classes and objects": a list is an object, and the variable points to it.More precisely, if you are curious
You make a real copy with a new list and a loop:
prices = [10, 20, 30]sale = []for price in prices: sale.append(price)sale[0] = 5print(prices[0], sale[0])10 5prices.copy() does the same:
prices = [10, 20, 30]sale = prices.copy()sale[0] = 5print(prices[0], sale[0])10 5Try it
Put the lines in order
The program should find the lowest price. Put its lines in order.
print(lowest)lowest = prices[0]prices = [18, 7, 25, 12]for i in range(1, len(prices)):if prices[i] < lowest:lowest = prices[i]
Exercise
Working with a list
Solve the exercises in your editor. Each program first reads how many numbers there are, then the numbers themselves, one per line:
n = int(input())numbers = []for i in range(n): numbers.append(int(input()))1. Sum, even, odd. Print the sum of all the numbers, of the even ones and of the odd ones.
3123Sum: 6Even: 2Odd: 42. Reversed. Create a new list with the same numbers in reverse order and print it on one line.
5123455 4 3 2 13. Lowest, highest, average. In one pass through the list, without the ready-made min, max and sum.
549274Lowest: 2Highest: 9Average: 5.2Exercise
Sorting and counting
4. Sorting. Sort the numbers from the smallest to the biggest. Hint: go through the list, and if two neighbors are in the wrong order, swap them (swapping is from the lesson on variables). Repeat until there is nothing left to swap. This is called bubble sort: the big numbers "bubble up" to the end. Don't use the ready-made numbers.sort(): the goal is to write it yourself.
5427193253 7 19 25 425. Longest run. Find the longest run of equal numbers one after another.
822555155The number 5, 3 times in a row6. Grade statistics. Read grades from 2 to 6 and print how many there are of each kind. Hint: a list counts with 7 elements, where the grade is the index: counts[grade] += 1.
864563265Excellent (6): 3Very good (5): 2Good (4): 1Fair (3): 1Poor (2): 1More exercises
- Median. The number in the middle of the sorted list. For 3, 1, 4, 1, 5 the median is 3. If there is an even count of numbers, the median is the average of the two in the middle: for 7, 1, 3, 9 it is (3 + 7) / 2 = 5.
- Symmetric list. Does it read the same from front to back and from back to front? 1 2 3 2 1 is symmetric, 1 2 3 1 is not.
- Roman numerals. Read a number from 1 to 3999 and print it in Roman numerals: 2024 is MMXXIV, 1994 is MCMXCIV. Hint: two lists side by side, with the values
1000, 900, 500, 400, 100, …, 1and with the symbols"M", "CM", "D", "CD", "C", …, "I". While the number is at least the current value, add the symbol and subtract the value.
Test