Open the contacts on a phone: hundreds of names, each with a number, and you find one by typing a few letters of the name. Open a mobile wallet’s statement: a long line of payments, newest first. Open the Brihat Shabdakosh: a word, then its meaning, tens of thousands of times over. Look at a class register: a row for each student, a column for each subject. None of these is one value. Each is a lot of values, held in a particular shape, and the shape is what makes the job easy: a statement is read in order, a contact is found by name, a register is read across a row or down a column.
In Grade 8 you kept one value in each variable, and met lists only as far as searching and sorting needed. Real programs handle hundreds, thousands or millions of values. In this unit you will learn Python’s three ways of holding many values at once: lists, kept in order and numbered; strings, which are lists of characters; and dictionaries, which find a value by its name. You will count words in a Nepali or English paragraph, read a table of Nepal’s provinces from a file and answer questions about it, and, most important of all, learn to choose the right shape for a job, because once the data is held the right way, the rest of the program is easy.
Lists: many values in order
In Grade 8 you met the list: values in square brackets, separated by commas, each item at its position (its index), counting from 0. len() gives the number of items, so the positions run from 0 to len(list) - 1, and a position past the end stops the program with an IndexError. The word in asks whether a value is in the list. Here is all of that in four lines, to remind you:
marks = [52, 38, 71, 45, 60]print(marks[0], marks[4])print(len(marks))print(38 in marks, 99 in marks)Output
52 605True FalseA list can hold any values: numbers, strings, True and False, even other lists (you will need that for tables later in this unit). It can hold the same value twice, and it keeps its items in the order you put them in.
Counting from the end
Python also numbers the items from the back, with minus numbers: marks[-1] is the last item, marks[-2] the one before it, and so on back to marks[-5], the first. So the last item is always marks[-1], however long the list, with no len() to work out.
marks = [52, 38, 71, 45, 60]print(marks[-1])print(marks[-2])print(marks[len(marks) - 1])Output
604560Going through the items
In Grade 8 you went through a list by its positions: for i in range(len(marks)):, then marks[i]. When you only need the items, not where they are, a for loop can take the items themselves, one at a time:
names = ["Sita", "Bikash", "Gita"]for name in names: print("Namaste,", name)Output
Namaste, SitaNamaste, BikashNamaste, GitaEach time round, the loop variable name holds the next item: first "Sita", then "Bikash", then "Gita". It is shorter, and there is no position to get wrong. Use range(len(…)) only when you need the position itself: to print it, to look at the item after it (as bubble sort did), or to change the item in the list.
Adding and removing items
A list can grow and shrink while the program runs. A tea shop keeps its orders in a list: new ones go on the end, and the one at the front is made first. A list has its own functions for this, written after the list’s name with a dot, like .lower() for strings in Grade 8. They are called methods.
| Method | What it does | orders after it, from ["tea", "momo"] |
|---|---|---|
orders.append("chiya") |
puts an item on the end | ["tea", "momo", "chiya"] |
orders.insert(0, "coffee") |
puts an item at a position; the rest move along | ["coffee", "tea", "momo"] |
orders.pop() |
takes out the last item and gives it back | ["tea"] (gives back "momo") |
orders.pop(0) |
takes out the item at a position and gives it back | ["momo"] (gives back "tea") |
orders.remove("momo") |
takes out the first item equal to this value | ["tea"] |
orders.index("momo") |
gives back the position of the first item equal to it; the list doesn’t change | (gives back 1) |
orders.count("tea") |
gives back how many items equal it | (gives back 1) |
orders.sort() |
sorts the list itself (Grade 8: it gives back None) |
["momo", "tea"] |
To change an item, set its position, as in Grade 8: orders[1] = "veg momo". To take out an item by its position without keeping it, del orders[1] works too.
Building a list as you go
Often a list starts empty, [], and a loop fills it with append(), just as a running total starts at 0 and a loop adds to it. Here a teacher types four marks, and the program keeps every one of them:
marks = []for i in range(4): m = int(input("Marks: ")) marks.append(m)print(marks)print(len(marks), "marks kept")Output
Marks: 72Marks: 65Marks: 80Marks: 58[72, 65, 80, 58]4 marks keptIn Grade 8’s five-subject program, each new mark replaced the last one in the variable, and only the total survived. Now every mark is kept, so the program can use them again later: sort them, find the second highest, or print them in a report.
queue = ["Asha", "Bimal", "Chhiring"]. After queue.pop(0) and then queue.append("Dolma"), what is the list?
Pick an answer to see why.
names = ["Sita", "Ram", "Gita", "Hari"]. What is names[-2]?
Pick an answer to see why.
Working through a list
Once values are in a list, a short loop can answer almost any question about them. You know the patterns from Grade 8: a running total, a counter, the highest so far. On a list, add one more: filtering, making a new list of only the items that pass a test.
Here is a week of rain at a weather station near Pokhara, in millimeters (made-up numbers), with a running total and a filter in the same loop:
rain = [0, 12, 30, 0, 5, 0, 18]total = 0wet = []for r in rain: total = total + r if r > 10: wet.append(r)print("Total:", total, "mm")print("Days over 10 mm:", wet)Output
Total: 65 mmDays over 10 mm: [12, 30, 18]Python’s own helpers
Some questions are asked so often that Python answers them for you, on any list of numbers:
rain = [0, 12, 30, 0, 5, 0, 18]print(sum(rain), max(rain), min(rain), len(rain))print(sum(rain) / len(rain))print(sorted(rain))print(rain.count(0), "dry days")print("Wettest: day", rain.index(max(rain)) + 1)Output
65 30 0 79.285714285714286[0, 0, 0, 5, 12, 18, 30]3 dry daysWettest: day 3sum() is the running total, max() and min() the highest and lowest so far, written for you. rain.index(30) is a linear search (Grade 8): it gives the position of the first 30. Positions count from 0 but days from 1, hence the + 1. Use these helpers freely; write the loop yourself when you need something they don’t do, such as a filter, or a total of only some items.
What does max([12, 5, 30, 18]) - min([12, 5, 30, 18]) give?
Pick an answer to see why.
Strings: text, a character at a time
A string is a sequence too: its characters are in order, numbered from 0, exactly like a list’s items. So everything you know about positions works on text: len() counts the characters, city[0] is the first, city[-1] the last, and a for loop goes through it a character at a time. (In Unit 2 you used text[i] to find runs of letters.)
city = "Bhaktapur"print(city[0], city[4], city[-1])print(len(city))for ch in "Nepal": print(ch)Output
B t r9NepalA space, a comma and a digit are characters too, each with its own position.
Slices
Often you want a piece of a string, or of a list: the first four letters of a name, the last four digits of a phone number, the top three marks. A slice gives you that piece. city[2:5] is the characters from position 2 up to, but not including, position 5, just as range(2, 5) gives 2, 3 and 4.
The easiest way to think of a slice is to put the numbers on the cuts between the characters, not on the characters. city[2:5] cuts at 2 and at 5, and takes what is between: 5 − 2 = 3 characters.
city = "Bhaktapur"print(city[2:5])print(city[:4])print(city[5:])print(city[-3:])print(city[::-1])Output
aktBhakapurpurrupatkahBThe last one has a third number, a step, like range()’s: [::-1] goes through the whole string backwards, so it reverses it.
Slices of lists work the same way. marks[:3] is a new list of the first three marks, sorted(marks)[-3:] the three highest, and marks[:] a copy of the whole list (one more way to copy, besides .copy()).
Strings can’t be changed
A list’s items can be changed: marks[0] = 55. A string’s characters can’t. Try to correct a name’s first letter:
name = "sita"name[0] = "S"Error message
Traceback (most recent call last): File "main.py", line 2, in <module> name[0] = "S" ~~~~^^^TypeError: 'str' object does not support item assignmentA string is immutable: once made, it never changes. Instead you make a new string and put it in the variable: name = "S" + name[1:] joins "S" to everything from position 1 on, and gives "Sita". Every string method below works the same way: it never changes the string, it gives back a new one.
String methods
Strings have many methods. These are the ones you will use most:
| Method | What it gives back | Example | Gives |
|---|---|---|---|
s.lower(), s.upper() |
all small, all capital letters | "Nepal".upper() |
"NEPAL" |
s.strip() |
without spaces at the start and end | " tea ".strip() |
"tea" |
s.strip(".,!") |
without those characters at the ends | "Namaste!".strip(".,!") |
"Namaste" |
s.replace(a, b) |
every a changed to b |
"984-123".replace("-", "") |
"984123" |
s.count(a) |
how many times a comes in it |
"Kathmandu".count("a") |
2 |
s.find(a) |
where a first starts, or −1 if it isn’t there |
"Kathmandu".find("man") |
4 |
s.startswith(a), s.endswith(a) |
True or False |
"Kathmandu".startswith("Kath") |
True |
s.isdigit() |
True if every character is a digit |
"2082".isdigit() |
True |
s.center(n) |
the string in the middle of n characters, spaces on both sides |
"tea".center(7) |
" tea " |
s.split(), s.split(",") |
a list of the pieces (next section) | "a,b".split(",") |
["a", "b"] |
in works on strings too, as in Grade 8’s project, and finds a piece anywhere inside: "man" in "Kathmandu" is True.
code = "NP-977-2082". What is code[3:6]?
Pick an answer to see why.
word = "momo". What does word.upper() do to word?
Pick an answer to see why.
Words and lines: split and join
Text usually comes as one long string: a message, a paragraph, a line of a file. To work on its parts, cut it up. split() cuts a string at every space (any run of spaces, tabs or new lines) and gives back a list of the pieces:
sentence = "the tea is hot and the momo is hot too"words = sentence.split()print(words)print(len(words), "words")Output
['the', 'tea', 'is', 'hot', 'and', 'the', 'momo', 'is', 'hot', 'too']10 wordsGive it a character, and it cuts there instead. A line of a class record, with its values separated by commas, becomes a list of values:
line = "Sita,72,65,80"parts = line.split(",")print(parts)print(parts[0], int(parts[1]) + int(parts[2]) + int(parts[3]))Output
['Sita', '72', '65', '80']Sita 217The pieces are always strings, even when they look like numbers, so turn them into numbers with int() or float() before you calculate, as with input().
join() does the opposite: it glues a list of strings together, with the string before the dot between them.
places = ["Kathmandu", "Lalitpur", "Bhaktapur"]print(", ".join(places))print(" → ".join(places))Output
Kathmandu, Lalitpur, BhaktapurKathmandu → Lalitpur → BhaktapurCleaning words
Real text has capital letters and punctuation stuck to its words: "Namaste!" and "namaste" are different strings. Clean each word before you use it:
text = "Namaste! Namaste, everyone. Welcome to Nepal."words = []for w in text.split(): words.append(w.strip(".,!?").lower())print(words)Output
['namaste', 'namaste', 'everyone', 'welcome', 'to', 'nepal']Nepali text needs one more character stripped: the danda, ।, Nepali’s full stop. "हुँ।".strip("।") gives "हुँ". Nepali has no capital letters, so .lower() leaves it as it is.
Now a question: how many times does each word come in a paragraph? A list of words can’t answer it easily. You would need a second list of counts, and to search the first list every time to find where each word’s count is. There is a better shape for this job.
What does "10,20,30".split(",") give?
Pick an answer to see why.
Dictionaries: looking things up by name
Nobody finds a word in the Brihat Shabdakosh by its number (“the 23,481st word”). You look it up by the word itself, and find its meaning. Nobody calls a friend by remembering “the 47th contact”; you look up the name and find the number. A list finds a value by its position. A dictionary finds a value by its key: a name you choose for it.
A dictionary is written in curly brackets, { }, as key–value pairs: each key, a colon, its value, with commas between the pairs. Look a value up with its key in square brackets:
menu = {"tea": 25, "coffee": 60, "samosa": 30}print(menu["coffee"])menu["momo"] = 150print(menu)menu["tea"] = 30print(menu)print(len(menu))print("momo" in menu, "pizza" in menu)del menu["coffee"]print(menu)Output
60{'tea': 25, 'coffee': 60, 'samosa': 30, 'momo': 150}{'tea': 30, 'coffee': 60, 'samosa': 30, 'momo': 150}4True False{'tea': 30, 'samosa': 30, 'momo': 150}The rules:
menu["momo"] = 150adds a key that isn’t there yet, andmenu["tea"] = 30changes the value of one that is. The same line does both: setting a key’s value makes the key if it is new.- Each key comes once. Two items can have the same value (tea and samosa both cost Rs 30), but not the same key. Write a key twice in the curly brackets,
{"tea": 25, "tea": 30}, and the last value replaces the first: the dictionary is{'tea': 30}. inasks whether a key is in the dictionary."momo" in menuisTrue;150 in menuisFalse, because 150 is a value, not a key.len()counts the pairs, anddel menu["coffee"]takes a pair out.- A dictionary keeps its pairs in the order they were added (Python has promised this since version 3.7, in 2018).
- Keys are usually strings or numbers. Values can be anything: numbers, strings, lists, even other dictionaries.
A key that isn’t there
Looking up a key that isn’t in the dictionary stops the program:
menu = {"tea": 25, "coffee": 60, "samosa": 30}print(menu["pizza"])Error message
Traceback (most recent call last): File "main.py", line 2, in <module> print(menu["pizza"]) ~~~~^^^^^^^^^KeyError: 'pizza'A KeyError names the key it couldn’t find. When a key might be missing, either ask first with in, or use get(), which gives back a default you choose instead of stopping:
words = {"water": "पानी", "fire": "आगो", "sun": "सूर्य", "book": "पुस्तक"}word = input("English word: ")print(words.get(word.lower(), "not in my dictionary yet"))Output
English word: Sunसूर्यRun it again with a word that isn’t a key, such as moon. This is a tiny English–Nepali dictionary: a dictionary in both senses.
Going through a dictionary
A for loop over a dictionary goes through its keys. To get each key with its value, loop over .items(), which gives the pairs; .values() gives only the values.
menu = {"tea": 25, "coffee": 60, "samosa": 30}for item in menu: print(item, menu[item])for item, price in menu.items(): print(f"{item}: Rs {price}")print("All three:", sum(menu.values()))Output
tea 25coffee 60samosa 30tea: Rs 25coffee: Rs 60samosa: Rs 30All three: 115for item, price in menu.items(): has two loop variables: each time round, the key goes into item and its value into price.
ages = {"Asha": 14, "Bimal": 15}. What does ages["Chhiring"] = 14 do?
Pick an answer to see why.
menu = {"tea": 25, "samosa": 30}. Which is True?
Pick an answer to see why.
Counting with a dictionary
Back to the question a list couldn’t answer easily: how many of each? Six students vote for class captain. A dictionary of counts answers it: the key is a name, the value its votes so far.
votes = ["Sita", "Bikash", "Sita", "Asha", "Sita", "Bikash"]counts = {}for name in votes: if name in counts: counts[name] = counts[name] + 1 else: counts[name] = 1print(counts)Output
{'Sita': 3, 'Bikash': 2, 'Asha': 1}This is the tally pattern: a dictionary used as a whole row of counters, one for each different thing, made as each new thing turns up. Lines 4 to 7 are so common that Python programmers usually write them as one line with get(): counts[name] = counts.get(name, 0) + 1 (the count so far, or 0 for a new name, plus 1).
To find the winner, use the highest-so-far pattern from Grade 8 on the pairs:
counts = {"Sita": 3, "Bikash": 2, "Asha": 1}winner = ""most = 0for name, n in counts.items(): if n > most: winner = name most = nprint(winner, "wins with", most, "votes")Output
Sita wins with 3 votesWhy a dictionary is fast
To find a contact in a list of 1,000 names, Grade 8’s linear search could need 1,000 comparisons, or 10 with binary search on a sorted list. A dictionary of 1,000 names usually needs just one or two looks, and it needs no more for a million. It doesn’t search at all. From the key itself, it works out where the value is kept, and goes straight there. The way it works this out is called hashing, and Unit 4 counts the steps of all three ways.
Tables: rows and columns
A class register, a bus timetable, a table of Nepal’s provinces: much of the world’s data comes as a table, with a row for each thing and a column for each fact about it. In Python a table is most simply a list of rows, each row itself a list:
rows = [ ["Koshi", 14, 4961412], ["Madhesh", 8, 6114600], ["Bagmati", 13, 6116866],]print(rows[2])print(rows[2][0], rows[2][2])print(len(rows), "rows")Output
['Bagmati', 13, 6116866]Bagmati 61168663 rowsrows[2] is one row, a list. rows[2][2] takes that row, then the item at position 2 in it: read it as “row 2, then position 2”. A list written over several lines, as here, is still one list: Python reads on until the closing bracket.
for row in rows: gives one whole row each time round. Adding up row[1] from every row is a total of a column; adding up the numbers along one row, a total of a row. To reach every value, put one loop inside another, a nested loop: the outer loop takes each row, the inner loop each position along it.
A photo is a table of numbers
A photo is a grid of pixels, each kept as a number (Unit 2). In a black-and-white photo with 8 bits a pixel, each pixel is a gray value from 0 (black) to 255 (white): the photo is a list of rows of gray values.
from nyatapola import photo takes the list photo from that file. show_grid(), from this page’s pixels module, draws a list of rows as a picture, a square for each value (on a computer, the Pillow library does this). This program draws the photo, then its negative, dark and light swapped:
from nyatapola import photofrom pixels import show_grid print(len(photo), "rows of", len(photo[0]), "pixels")print("Top left:", photo[0][0])print("Middle:", photo[15][20])show_grid(photo) negative = []for r in range(len(photo)): row = [] for c in range(len(photo[0])): row.append(255 - photo[r][c]) negative.append(row)show_grid(negative)Output
30 rows of 40 pixelsTop left: 235Middle: 30Picture
photo[r][c] is the pixel r rows down and c across, from 0 at the top left. The outer loop (line 10) goes down the rows, the inner loop (line 12) along each row, and 255 - photo[r][c] turns dark to light. Each new row is built with append(), then appended to negative: 30 rows of 40, 1,200 pixels.
Reading a table from a file
Nobody types a big table into a program. Tables are kept in files, and the simplest kind is a CSV file (comma-separated values): plain text, one row on each line, the values separated by commas, and usually the column names on the first line. A spreadsheet can save any sheet as a CSV file (Grade 7). Here is the whole table of provinces from the 2021 census, as a CSV file:
provinces.csv
province,districts,populationKoshi,14,4961412Madhesh,8,6114600Bagmati,13,6116866Gandaki,11,2466427Lumbini,12,5122078Karnali,10,1688412Sudurpashchim,9,2694783A program on this page can read that file, as a program on a computer reads a file in its folder. open() opens it, .read() gives its whole text as one string, and .close() closes it. Then three steps you already know turn the text into a table: splitlines() cuts the text into its lines, split(",") cuts each line into its values, and int() turns the numbers from strings into numbers.
file = open("provinces.csv")text = file.read()file.close()lines = text.splitlines()print(lines[0])print(lines[3])rows = []for line in lines[1:]: parts = line.split(",") rows.append([parts[0], int(parts[1]), int(parts[2])])print(rows[2])print(len(rows), "provinces")Output
province,districts,populationBagmati,13,6116866['Bagmati', 13, 6116866]7 provincesLine 8 loops over lines[1:], a slice that leaves out line 0, the column names. Each line becomes a row of three values, two of them turned into ints, and is appended to rows.
Now any question about the provinces is a short loop. Here the reading is a function, so the questions can be asked below it:
def read_provinces(filename): """Return the table as a list of rows: name, districts, population.""" file = open(filename) lines = file.read().splitlines() file.close() rows = [] for line in lines[1:]: parts = line.split(",") rows.append([parts[0], int(parts[1]), int(parts[2])]) return rows rows = read_provinces("provinces.csv")total = 0biggest = rows[0]for row in rows: total = total + row[2] if row[2] > biggest[2]: biggest = rowprint("Nepal:", total, "people")print("Most people:", biggest[0], biggest[2])for row in rows: print(f"{row[0]}: {row[2] // row[1]} people a district")Output
Nepal: 29164578 peopleMost people: Bagmati 6116866Koshi: 354386 people a districtMadhesh: 764325 people a districtBagmati: 470528 people a districtGandaki: 224220 people a districtLumbini: 426839 people a districtKarnali: 168841 people a districtSudurpashchim: 299420 people a districtThe total, 29,164,578, is Nepal’s population in the 2021 census, which checks that every row was read. Bagmati has the most people, but only just: Madhesh has 2,266 fewer. And Madhesh’s districts have the most people each, more than four times Karnali’s, because it has only 8 districts on the crowded plains of the Tarai.
Writing a file
A program can also write a table to a file, for a spreadsheet or another program to read later. open() takes a second string, the mode, which says what you will do with the file:
| Mode | What it does |
|---|---|
"r" |
read the file (the mode when you give none); an error if the file isn’t there |
"w" |
write a new file; if the file is already there, everything in it is wiped first |
"a" |
append: write at the end of the file, after what is already in it |
"x" |
write a new file, but stop with an error if the file is already there |
write() puts a string into the file. Unlike print(), it doesn’t start a new line by itself, so each line ends with "\n", the new-line character, and numbers must be turned into strings with str():
results = [["Asha", 72], ["Bimal", 58], ["Chhiring", 90]]file = open("results.csv", "w")file.write("name,marks\n")for name, marks in results: file.write(name + "," + str(marks) + "\n")file.close() file = open("results.csv", "a")file.write("Dolma,64\n")file.close() file = open("results.csv", "r")print(file.read().strip())file.close()Output
name,marksAsha,72Bimal,58Chhiring,90Dolma,64Lines 2 to 6 write a new file, the column names and then one line per row. Lines 8 to 10 open it again with "a" and add a fifth line at the end. Lines 12 to 14 read it all back (strip() takes off the last new line). Run it twice: the file still has five lines, because "w" wipes it each time.
Many programs, and CDC’s books, open a file with with, which closes it by itself at the end of the block, even if the program stops with an error:
with open("results.csv", "r") as file: text = file.read()Tuples: rows that don’t change
Python has one more sequence, the tuple: values in round brackets, ("Bagmati", 13, 6116866). A tuple is like a list in every way you read it (positions, len(), slices, in, a for loop), but like a string it can’t be changed: no append(), no setting an item. Use a tuple for a group of values that belong together and shouldn’t change, such as a point’s x and y, or a date’s year, month and day.
row = ("Bagmati", 13, 6116866)row[1] = 14Error message
Traceback (most recent call last): File "main.py", line 2, in <module> row[1] = 14 ~~~^^^TypeError: 'tuple' object does not support item assignmentYou have used tuples already without knowing: for item, price in menu.items(): takes each pair as a tuple and unpacks it into two variables. Unpacking works on any sequence of the right length:
row = ("Bagmati", 13, 6116866)name, districts, people = rowprint(name, people)a = 5b = 9a, b = b, aprint(a, b)Output
Bagmati 61168669 5a, b = b, a is the swap promised in Grade 8: Python makes the tuple (9, 5) on the right first, then unpacks it into a and b. No temp is needed. A function can give back two values the same way: return low, high returns one tuple, which the caller can unpack.
def lowest_and_highest(marks): return min(marks), max(marks) low, high = lowest_and_highest([52, 38, 71, 45])print(low, high)Output
38 71A list of dictionaries
In a list of rows you must remember that position 2 is the population. If a column is added in the middle one day, every row[2] in the program is suddenly wrong. Each row can be a dictionary instead, its keys the column names:
rows = [ {"province": "Koshi", "districts": 14, "population": 4961412}, {"province": "Karnali", "districts": 10, "population": 1688412},]for row in rows: print(row["province"], row["population"])Output
Koshi 4961412Karnali 1688412row["population"] says what it is; row[2] doesn’t. A list of dictionaries is longer to type, but easier to read and harder to get wrong, and it is how most tables arrive from websites (Grade 10 calls this format JSON).
table = [["Asha", 72, 65], ["Bimal", 58, 80]]. What is table[1][2]?
Pick an answer to see why.
Which can’t be changed once it is made?
Pick an answer to see why.
Choosing a data structure
Lists, strings, tuples and dictionaries are Python’s main data structures: ways of holding many values so that a program can store them, find them and change them. Choosing the right one is often the biggest decision in a program. Ask these questions about your data:
| Ask | If yes | Example |
|---|---|---|
| Is it text? | a string; split() it when you need its words or values |
a message, a line of a file |
| Do you look things up by a name? | a dictionary, the name as its key | an item’s price; a word’s meaning; a district’s province |
| Do you count how many of each? | a dictionary of counts (a tally) | votes, words, items sold |
| Does the order matter, or do you go through all of it? | a list | marks to average; a queue; songs in a playlist; a day’s readings |
| Is it a few values that belong together and never change? | a tuple | a date, a point’s x and y |
| Is it a table? | a list of rows: each row a list, or a dictionary with the column names as keys | a class register; the provinces |
Two warning signs that the structure is wrong: searching a list again and again for a name (use a dictionary), and keeping two lists side by side whose items must match up, names[i] with marks[i] (use one list of rows, or a dictionary from name to marks).
Designing with data structures
To design a program, decide the data first, then the algorithm. Here is a design done step by step.
Reading code with lists and dictionaries
Programmers read more code than they write. When a function works with lists or dictionaries, read it by asking four questions: What does each parameter hold, and of what type? What does it return? Does it change the list or dictionary it was given? And why does it use this data structure?
The last two matter more than they seem. In Grade 8, bubble_sort(names) changed the list it was given, while sorted() gave back a new one. A function that takes a list can do either, and a program that calls it must know which.
def with_bonus(marks, bonus): new = [] for m in marks: new.append(m + bonus) return new def add_bonus(marks, bonus): for i in range(len(marks)): marks[i] = marks[i] + bonus science = [52, 38, 71]better = with_bonus(science, 5)print(science, better)add_bonus(science, 5)print(science)Output
[52, 38, 71] [57, 43, 76][57, 43, 76]Project
In short
Exercise
fruits = ["mango", "litchi", "banana"]. What does fruits.append("orange") do?
Pick an answer to see why.
What is "Pokhara"[1:4]?
Pick an answer to see why.
Which line makes a dictionary?
Pick an answer to see why.
What does "a b c".split() give?
Pick an answer to see why.
stock = {"pens": 40, "copies": 25}. What does stock.get("rulers", 0) give?
Pick an answer to see why.
A program keeps a diary in diary.txt. Each day it must add that day’s line without losing the days before. How should it open the file?
Pick an answer to see why.
A program must remember each district’s headquarters, and find it from the district’s name. Which is best?
Pick an answer to see why.
What is a data structure? Name four of Python’s, with an example of each written as Python, and say one job each suits.
Answer
colors = ["blue", "white", "red", "green", "yellow"]. Give the value of each: i. colors[1] ii. colors[-1] iii. colors[1:3] iv. colors[:2] v. len(colors[2:]) vi. colors.index("red")
Answer
Write the output of this program.
nums = [4, 7, 1]nums.append(9)nums.insert(1, 5)x = nums.pop()nums.remove(7)print(nums, x)Answer
What is the difference between a list and a dictionary? Explain with an example of the same data kept both ways, and say which you would choose for it, and why.
Answer
Write a program that asks for a sentence and prints how many words it has, the longest word, and the sentence with its words in reverse order.
Answer
Write a program that counts how many times each letter comes in a word the user types, using a dictionary. Show its output for banana.
Answer
A student wants to give everyone’s marks a bonus of 5, but this program prints the old marks. Explain why, and correct it in two different ways.
marks = [52, 38, 71]for m in marks: m = m + 5print(marks)Answer
Here is part of a CSV file of bus fares from Kathmandu (made-up fares). Write a program that reads lines like these from a string into a dictionary from town to fare, then prints the fare to Pokhara, and the cheapest town.
Fares
Pokhara,1200Chitwan,900Butwal,1100Dhulikhel,150Answer
Blur the Nyatapola photo: each new pixel is the average of the old one and its neighbors (the 3 × 3 square around it, fewer at the edges). Draw it. Why do the temple’s edges go soft?
Hint
Answer
A shop wants a program to keep its stock: how many of each item it has, and to take an item off when one is sold, refusing a sale when none is left. Design it: choose the data structure and say why, write the algorithm for one sale in pseudocode, then write it as a Python function sell(stock, item) that returns True for a sale and False when it can’t sell.
Answer
Quiz yourself: Algorithms and programming, Grades 6–12 →
Practice every question in the book, and keep track of the ones you miss →
