Lesson 05
Nested Lists, 2D Lists, and Matrices
Work with inner lists, multi-level indexing and slicing, matrix rows, nested loops, combining 2D lists, and shallow copy pitfalls.
What you will learn
Nested Lists · 2D Lists · Matrices
A nested list is simply a list inside another list. It is the foundation for tables, seating charts, spreadsheets, game boards, and matrices.
| Concept | Meaning |
|---|---|
| Nested list | List element that is itself a list |
| Matrix | List of rows, each row a list |
matrix[i][j] |
Row i, column j |
Memory formula: Row → Column → Cell
After File 04 — sort, copy, and del, you can organize rows safely — this lesson shows how to structure and traverse 2D data.
Learning roadmap
1. What is a nested list?
A nested list contains another list as an element.
Visual structure
lst = [10, "RS", [1, 2, 3], 45.67]
print(lst[2]) # Inner list
print(lst[2][1]) # Second value inside inner listOutput:
[1, 2, 3]
2Think of it like this:
lst[2]→ entire inner listlst[2][1]→ one value inside that list
2. Multi-level indexing
A matrix uses two indexes: row first, then column.
matrix = [
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
]
print(matrix[1][2]) # 60Formula
matrix[row][column]
| Expression | Meaning |
|---|---|
matrix[0] |
First row |
matrix[1] |
Second row |
matrix[1][2] |
Row 1, column 2 |
3. Updating inner lists
Each row is a normal Python list — use list methods on matrix[row_index].
data = [["A", "B"], ["X", "Y"]]
data[0].append("C")
print(data) # [['A', 'B', 'C'], ['X', 'Y']]You can also modify values directly:
data[1][0] = "Z"
print(data) # [['A', 'B', 'C'], ['Z', 'Y']]4. Slicing inside nested lists
Slicing works at each level.
row = [
[1, 2, 3, 4],
[5, 6, 7, 8]
]
print(row[0][1:3]) # [2, 3]Rule: First choose the row, then slice the columns.
5. Iterating through rows
Simple row loop
matrix = [
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
]
for row in matrix:
print(row)Output:
[10, 20, 30]
[40, 50, 60]
[70, 80, 90]Each iteration gives one entire row.
6. Access every cell (nested loop)
for i, row in enumerate(matrix):
for j, value in enumerate(row):
print(f"({i},{j}) = {value}")Visual traversal
Output begins like this:
(0,0) = 10
(0,1) = 20
(0,2) = 30
...This pattern is used in spreadsheets, games, and image processing.
7. Combining two matrices
The + operator joins rows, not numbers.
m1 = [[10, 20], [30, 40]]
m2 = [[1, 2], [3, 4]]
combined = m1 + m2
print(combined)Output:
[[10, 20], [30, 40], [1, 2], [3, 4]]It does not produce
[[11, 22], ...]. That requires mathematical addition (loops or NumPy).
8. Shallow copy warning (most important)
This is one of the most common interview questions.
a = [[1, 2], [3, 4]]
b = a.copy()
b[0].append(99)
print(a) # [[1, 2, 99], [3, 4]]
print(b) # [[1, 2, 99], [3, 4]]Why?
copy() duplicates the outer list only. Inner list objects are still shared. See Aliasing and Copying for the full picture.
Safe deep copy
import copy
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)Now both inner lists become independent.
Mini project — classroom seating chart
Imagine a classroom arranged in rows.
seating = [
["A1", "A2", "A3"],
["B1", "B2", "B3"]
]
for row in range(len(seating)):
for col in range(len(seating[row])):
print(f"Row {row}, Col {col}: {seating[row][col]}")Visual classroom
Output:
Row 0, Col 0: A1
Row 0, Col 1: A2
Row 0, Col 2: A3
Row 1, Col 0: B1
...One-page revision sheet
| Task | Syntax |
|---|---|
| Access row | matrix[i] |
| Access cell | matrix[i][j] |
| Update value | matrix[i][j] = x |
| Add to row | matrix[i].append(x) |
| Slice columns | matrix[i][1:3] |
| Loop rows | for row in matrix |
| Loop every cell | Nested for loop |
| Combine matrices | m1 + m2 |
Common interview mistakes
Mistake 1 — expecting + to add numbers:
m1 + m2 # joins rows only — not [[11, 22], ...]Correct: + concatenates the outer list.
Mistake 2 — assuming copy() is deep:
b = a.copy() # inner lists still sharedCorrect: Use copy.deepcopy() when inner lists must also be independent.
Practice questions
Test yourself before File 06 — Tuple Deep Dive:
- How do you access the value
90from a 3×3 matrix? - What is the difference between
matrix[1]andmatrix[1][0]? - Why does
matrix.copy()still share inner lists? - How do you print every cell with row and column numbers?
- What does
m1 + m2actually combine?
Knowledge check
Q1: How do you access 90 in a 3×3 matrix ending with [70, 80, 90]?
Answer: matrix[2][2] — row 2, column 2.
Q2: matrix[1] vs matrix[1][0]?
Answer: matrix[1] is the entire second row; matrix[1][0] is the first cell in that row.
Q3: Why does matrix.copy() share inner lists?
Answer: copy() is shallow — only the outer list is duplicated; inner list objects are reused.
Q4: Print every cell with row and column numbers?
Answer: Nested loop with enumerate, or for row in range(len(matrix)): with inner for col in range(len(matrix[row])):.
Q5: What does m1 + m2 combine?
Answer: The outer lists — all rows from m1 followed by all rows from m2.
Loading playground…