9.1 Creating a 2D Array
A 2D array is a list of lists. The outer list holds the rows; each inner list is one row of values. Python does not have a built-in array type the way Cambridge pseudocode does — instead we use nested lists.
matrix = [
[1, 2, 3], # Row 0
[4, 5, 6], # Row 1
[7, 8, 9] # Row 2
]
print(matrix)
# Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]| col 0 | col 1 | col 2 | |
|---|---|---|---|
| row 0 | 1 | 2 | 3 |
| row 1 | 4 | 5 | 6 |
| row 2 | 7 | 8 | 9 |
- The grid above has 3 rows and 3 columns — a 3×3 array.
- Each inner list is one row.
- The highlighted cell
matrix[1][1]is row 1, column 1 = 5.
Creating a 2D Array
9.2 Initialising a 2D Array
There are six ways to fill a 2D array. Which one you choose depends on whether you already know the values, or whether you need a blank grid of a fixed size to fill in later.
1 — Static (values known in advance)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]2 — Empty array (no data yet)
matrix = [] # add rows later with matrix.append(...)3 — Fixed size, filled with zeros
rows = 3
cols = 4
matrix = [[0 for _ in range(cols)] for _ in range(rows)]- Build a fixed-size grid with a nested comprehension (one inner comprehension per row).
- Never write
[[0]*cols]*rows— that makes every row the same list object. - Changing one row then secretly changes them all.
4 — Fixed size, any default value
rows = 2
cols = 3
matrix = [["-" for _ in range(cols)] for _ in range(rows)]5 — Fill from user input
rows = 2
cols = 3
matrix = []
for i in range(rows):
row = []
for j in range(cols):
value = int(input("Enter value: "))
row.append(value)
matrix.append(row)6 — Fill by reading a file
matrix = []
with open("data.txt", "r") as file:
for line in file:
row = [int(x) for x in line.strip().split(",")]
matrix.append(row)- Set the size in named variables (rows = 4, cols = 2)
- Use a nested comprehension so each row is its own list
- The default value is -1 (an integer)
- Same pattern as the zeros method
- The default value is a string ("Available") instead of a number
- Use a nested comprehension, never the * operator on the outer list
- The examiner gives marks for: (1) the correct size, (2) the correct starting value, and (3) using a loop/comprehension rather than typing the values by hand.
- If the question says "initialised", a hand-typed list usually scores 0 for the initialisation mark.
Initialising a 2D Array
9.3 Accessing Elements
To get one value you give the row index first, then the column index: matrix[row][col]. Both start counting at 0.
matrix = [
[1, 2, 3], # Row 0
[4, 5, 6], # Row 1
[7, 8, 9] # Row 2
]
print(matrix[0][1]) # row 0, col 1 -> 2
print(matrix[2][2]) # row 2, col 2 -> 9matrix[a][b]means "go to rowa, then move along to columnb".- Swapping them gives a different cell (or an error if the grid is not square).
- First index is 1 → go to row 1, which is [40,50,60]
- Second index is 2 → take column 2 of that row
- Count 0, 1, 2 → that is 60
- Work the row out first, then count along the columns from 0
- grid[0][2]: row 0 is [5,6,7], column 2 is 7
- grid[2][1]: row 2 is [11,12,13], column 1 is 12
- A very common slip is reading
matrix[col][row]by habit. - Write a tiny note in the margin — "row first" — and check it on every access.
- Examiners do not award the mark if the indices are the wrong way round.
Accessing Elements
9.4 Changing Elements
Assign a new value straight to the element using its two indices. This overwrites just that one cell — everything else stays exactly as it was.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix[1][1] = 50 # change the middle element 5 -> 50
print(matrix)
# Output: [[1, 2, 3], [4, 50, 6], [7, 8, 9]]matrix[row][col] = newValueoverwrites just that one cell.- Everything else stays exactly as it was.
- Locate the cell: row 1, column 2
- Assign the new value with seats[1][2] = "X"
- Print the grid to verify
- Only one index pair changes from the worked example
- Use seats[0][0] = "X"
- Print the grid
Changing Elements
9.5 Looping Through a 2D Array
The outer loop walks down the rows. For each row, the inner loop walks across its columns. After finishing a row, we print a newline to start the next one on a fresh line.
matrix = [[1, 2, 3], [4, 50, 6], [7, 8, 9]]
for row in matrix: # each inner list
for element in row: # each value in that row
print(element, end=" ")
print() # newline after each row
# Output:
# 1 2 3
# 4 50 6
# 7 8 9- If you need the index numbers (not just the values), loop with
range. for i in range(len(matrix))for rows, andfor j in range(len(matrix[i]))for columns.- Use
matrix[i][j]inside.
- Start a running total at 0 before the loops
- Outer loop over rows, inner loop over each value
- Add each value to the total
- Print the total after both loops finish
- Keep a variable biggest; start it at the first element (m[0][0])
- Compare every value against it
- If a value is bigger, update biggest
- Print biggest after both loops finish
- Counter at 0 before the loops
- Add 1 each time a value equals 0
- Loop through every row and every value
- Same counter pattern
- Swap the condition to v > 3
- Only 4 and 8 are greater than 3
Looping Through a 2D Array
9.6 Operations on a 2D Array
To work on whole rows, loop with an index i so you can grab the row as matrix[i] and use Python's sum() on it.
matrix = [[1, 2, 3], [9, 9, 9], [4, 0, 1]]
max_sum = -1
max_row = -1
for i in range(len(matrix)):
row_sum = sum(matrix[i])
if row_sum > max_sum:
max_sum = row_sum
max_row = i
print("Row", max_row, "has the highest sum:", max_sum)
# Output: Row 1 has the highest sum: 27sum(matrix[i])totals one row.- To total a column you cannot use
sumdirectly. - Loop over the rows and add
matrix[i][j]for the fixed columnj.
- Fix the column at 0; start a total at 0
- Loop over the rows with range(len(m))
- Add m[i][0] for each row
- Print the total (1+3+5 = 9)
- Loop columns with j (range(len(m[0])))
- For each j, total m[i][j] over all rows
- Track the maximum like the row example
- Column 0 = 1+2+3 = 6; column 1 = 5+5+5 = 15
- Start
max_sumat a value below any possible total (often-1or the first row's sum). - If you start it at 0 and every total could be 0 or negative, you may pick the wrong row.
- The examiner checks that the maximum is initialised safely.
Operations on a 2D Array
9.7 Reading a 2D Array from a File
Each line of the file becomes one row. Split the line on its separator, convert if needed, then append the row to the array.
# scores.txt:
# Musarrat,80,90,70
# Naib,85,75,95
# Mohar,78,88,82
data = []
with open("scores.txt", "r") as file:
for line in file:
parts = line.strip().split(",")
name = parts[0]
marks = [int(x) for x in parts[1:]]
data.append([name] + marks)
print(data)
# Output: [['Musarrat', 80, 90, 70], ['Naib', 85, 75, 95], ['Mohar', 78, 88, 82]].strip() each line before splitting, to remove the invisible newline character at the end — otherwise the last value carries a \n and number conversion fails.- Wrap the file work in try/except so a missing file does not crash
- Build a row per line, convert to integers
- Append each row to the grid
- Return the grid; print a message on error
- Split on the comma
- Keep element 0 as a string (name)
- Convert element 1 with int() (score)
- Append [name, score] to the records list
Reading from a File
9.8 Full Exam-Style Question
A school stores student names and three subject marks (Math, English, Science) in a text file scores.txt. Each line is Name,Math,English,Science:
Musarrat,80,90,70
Tarnima,85,75,95
Aymaan,78,88,82
Mehrin,92,85,79read_scores() that reads scores.txt into a 2D list studentData, where each row stores the name (string) followed by the three marks (integers), and returns the list.averages.txt in the format Name,M,E,S,Average.- (a) Read file, strip + split each line, convert marks to int, append [name] + marks
- (b) Loop through each row, average = (m1+m2+m3)/3, print name and round(average, 2)
- (c) Open averages.txt in "w" mode, write each row as Name,M,E,S,Average with newline
Mark scheme
| Part | Marking points (1 mark each unless stated) |
|---|---|
| (a) [5] |
|
| (b) [4] |
|
| (c) [4] |
|
✓ Key Points Summary
9.9 Practice Tasks
Fifteen exam-style 2D array tasks. Each shows only the question — click Hint for the thought process, or Help for the worked solution.
- For every 2D array task, the marker checks: (1) correct creation/initialisation, (2) correct indexing (row first, column second), (3) correct nested loop structure, (4) correct use of sum() for rows or manual loop for columns.
- The most common mark loss is using
[[0]*c]*rinstead of a nested comprehension.
Question Bank
Answer all questions, then press Submit Quiz to see your score.
Question 1Multiple Choice
A 2D array in Python is a:
Question 2True / False
In matrix[row][col], the row index comes before the column index.
Question 3Multiple Choice
Which correctly creates a 3×4 grid of zeros?
Question 4Multiple Choice
For grid = [[10,20,30],[40,50,60]], what is grid[0][2]?
Question 5True / False
[[0]*cols]*rows creates independent row lists.
Question 6Multiple Choice
How do you change the element at row 2, column 1 to 99?
Question 7Multiple Choice
In a nested loop over a 2D array, the outer loop walks the:
Question 8True / False
sum(matrix[i]) totals row i of a 2D array.
Question 9Multiple Choice
To total column j, you must:
Question 10Multiple Choice
When reading a 2D array from a file, what must you do to each line before splitting?
Question 11True / False
For "Musarrat,80,90,70", the correct way to get [80,90,70] as integers is [int(x) for x in parts[1:]].
Question 12Multiple Choice
When finding the row with the highest sum, max_sum should start at:
Answer all 12 questions to enable submission.