Python Basics — Nested Lists
Nested Lists
A nested list (or list of lists) is a list where each element is itself a list. This is how Python represents 2D data structures like matrices and grids.
Creating Nested Lists
# 2D list (matrix)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# List of mixed-length lists
jagged = [
[1, 2],
[3, 4, 5],
[6]
]
Accessing Nested Elements
Use double indexing — first index selects the row, second selects the column:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(matrix[0]) # [1, 2, 3] (first row)
print(matrix[1][2]) # 6 (second row, third column)
print(matrix[-1][-1]) # 9 (last row, last column)
Modifying Nested Elements
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix[0][0] = 99
print(matrix)
# [[99, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix[1] = [40, 50, 60]
print(matrix)
# [[99, 2, 3], [40, 50, 60], [7, 8, 9]]
Iterating Over Nested Lists
Simple Iteration
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for row in matrix:
for element in row:
print(element, end=" ")
print()
# 1 2 3
# 4 5 6
# 7 8 9
With Indices
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for i, row in enumerate(matrix):
for j, val in enumerate(row):
print(f"matrix[{i}][{j}] = {val}")
Flattening a Nested List
Using List Comprehension
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Using itertools.chain
from itertools import chain
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = list(chain.from_iterable(matrix))
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Creating Matrices Correctly
⚠️ Common Trap — Multiplied References
# ❌ WRONG — all rows share the same list object
matrix = [[0] * 3] * 3
matrix[0][0] = 99
print(matrix)
# [[99, 0, 0], [99, 0, 0], [99, 0, 0]] ← all rows changed!
✅ Correct — Comprehension
# ✅ CORRECT — each row is an independent list
matrix = [[0] * 3 for _ in range(3)]
matrix[0][0] = 99
print(matrix)
# [[99, 0, 0], [0, 0, 0], [0, 0, 0]] ← only first row changed
Deep Copy vs Shallow Copy
import copy
# Shallow copy — inner lists are still shared
original = [[1, 2], [3, 4]]
shallow = original[:]
shallow[0][0] = 99
print(original) # [[99, 2], [3, 4]] ← changed!
# Deep copy — fully independent
original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)
deep[0][0] = 99
print(original) # [[1, 2], [3, 4]] ← unchanged
Practical Examples
Matrix Transpose
matrix = [
[1, 2, 3],
[4, 5, 6]
]
transpose = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(transpose)
# [[1, 4], [2, 5], [3, 6]]
Using zip():
transpose = [list(row) for row in zip(*matrix)]
print(transpose)
# [[1, 4], [2, 5], [3, 6]]
Matrix Addition
a = [[1, 2], [3, 4]]
b = [[5, 6], [7, 8]]
result = [
[a[i][j] + b[i][j] for j in range(len(a[0]))]
for i in range(len(a))
]
print(result) # [[6, 8], [10, 12]]
Tic-Tac-Toe Board
board = [[" " for _ in range(3)] for _ in range(3)]
def print_board(b):
for row in b:
print(" | ".join(row))
print("-" * 9)
board[0][0] = "X"
board[1][1] = "O"
board[2][2] = "X"
print_board(board)
Output:
X | |
---------
| O |
---------
| | X
---------
Summary
- Nested lists are lists containing other lists
- Access with double indexing:
matrix[row][col] - Iterate with nested
forloops - Never create matrices with
[[val] * n] * m— use comprehensions - Shallow copies share inner objects — use
copy.deepcopy()for full independence - Flatten with
[item for row in matrix for item in row] - Transpose with
zip(*matrix)
Next up: Lists — Practice Exercises →