Python Nested Lists

In the last lesson you learned List Comprehensions. That was a short way to build a list. Now we go one step further. What if one box in your list needs to hold a whole row of things? Not just a single value. That is where a nested list comes in.

πŸ€” Why Nested Lists?

Some data is not a flat line. It comes as a grid. Think of a tic-tac-toe board. Think of a seating chart in a cinema. Think of a table of marks for a class. Each one has rows and columns.

A plain list can only hold a single row. So how do you keep three rows of a game board together in one place? You could make three separate lists. But then they drift apart. Your code gets messy fast.

A nested list fixes this. You put a list inside a list. Now one variable holds the whole grid. Neat and together.

🧩 What Is a Nested List?

A nested list is simply a list whose items are themselves lists.

Picture a spreadsheet. The whole sheet is one thing. Inside it sit rows. Each row is a strip of cells. That is exactly a nested list. The outer list is the sheet. Each inner list is one row.

Here is a small grid with two rows and three columns. Each inner list is one row.

grid = [
[1, 2, 3],
[4, 5, 6],
]
print(grid)

The outer list holds two items. Each item is itself a list of three numbers. When we print it, Python shows the lists nested inside.

Output

[[1, 2, 3], [4, 5, 6]]

So grid is one variable. But it carries the whole table.

πŸ”’ Reading One Item With Two Indexes

To pull a single value out of a flat list you use one index. With a nested list you use two. The first index picks the row. The second index picks the column inside that row.

Remember, Python counts from 0. So the first row is row 0. And the first column is column 0.

This reads the value in the second row, third column.

grid = [
[1, 2, 3],
[4, 5, 6],
]
value = grid[1][2]
print(value)

Read grid[1][2] left to right:

  • grid[1] gives the second inner list, which is [4, 5, 6].
  • then [2] picks the third item from that inner list, which is 6.

Output

6

The trick is to read it in two steps. First find the row. Then find the column inside that row.

Tip

A handy way to remember the order is grid[row][column]. Row first, column second. Just like saying β€œrow 2, seat 3” at a cinema.

Here is the same grid shown as a table so the indexes are easy to see.

Column 0 Column 1 Column 2
Row 0 1 2 3
Row 1 4 5 6

Find row 1, then column 2. They cross at 6. That is exactly what grid[1][2] gave us.

πŸ” Looping Over Every Value

Reading one item is fine. But often you want to touch every value in the grid. For that you use a nested loop. That is a loop inside a loop.

The outer loop walks through the rows. The inner loop walks through the items in the current row.

This loops over the whole grid and prints every number, one per line.

grid = [
[1, 2, 3],
[4, 5, 6],
]
for row in grid:
for value in row:
print(value)

Read it slowly:

  • the outer loop takes one row at a time, so row becomes [1, 2, 3], then [4, 5, 6].
  • for each row, the inner loop takes one value at a time and prints it.

Output

1
2
3
4
5
6

The outer loop runs twice, once per row. The inner loop runs three times for each of those, once per column. So the body runs six times in total, once for every cell.

β­• A Real Example: A Tic-Tac-Toe Board

Let us build something you can picture. A tic-tac-toe board is a grid of three rows and three columns. We will store it as a nested list. Then we print it so it looks like a real board.

We use "X", "O", and " " (a space) for an empty square.

board = [
["X", "O", "X"],
[" ", "X", "O"],
["O", " ", "X"],
]
for row in board:
print(" | ".join(row))

Here is what each part does:

  • the board is a nested list, one inner list per row of the game.
  • the outer loop takes one row at a time.
  • " | ".join(row) glues that row’s three cells into one line with a bar between them.

Output

X | O | X
| X | O
O | | X

Now you can read the board at a glance. And to check who sits in the centre square, you just ask for board[1][1].

This prints the value in the middle of the board.

board = [
["X", "O", "X"],
[" ", "X", "O"],
["O", " ", "X"],
]
print(board[1][1])

board[1] is the middle row [" ", "X", "O"]. Then [1] picks its middle cell.

Output

X

πŸ“Š Another Real Example: A Table of Marks

Grids are not only for games. Say Riya is a teacher with marks for a few students across two subjects. Each inner list is one student’s marks.

This stores the marks and prints a total for each student.

marks = [
[80, 90],
[70, 60],
[95, 88],
]
names = ["Alex", "Arjun", "Riya"]
for i in range(len(marks)):
total = marks[i][0] + marks[i][1]
print(f"{names[i]} scored {total}")

Walk through it:

  • marks is a nested list, one inner list of two marks per student.
  • range(len(marks)) gives us 0, 1, 2, one number per student.
  • marks[i][0] is that student’s first subject, marks[i][1] is the second.
  • the f-string then prints the name with the total.

Output

Alex scored 170
Arjun scored 130
Riya scored 183

One nested list held the whole table of marks. And two indexes let us reach any single mark we wanted.

⚠️ Common Mistakes

A few slips trip people up with nested lists. Watch for these.

First, mixing up the index order. The first index is the row. The second is the column. Swap them and you read the wrong cell. Or you crash.

grid = [[1, 2, 3], [4, 5, 6]]
# ❌ Avoid: thinking [2][1] is row 2, when there is no row 2
# print(grid[2][1]) # this would crash
# βœ… Good: row index first, then column
print(grid[1][2]) # 6

Next, going past the last index. A grid with two rows has rows 0 and 1 only. Asking for grid[2] reaches a row that is not there.

grid = [[1, 2, 3], [4, 5, 6]]
# ❌ Avoid: there is no third row
# print(grid[2])
# βœ… Good: stay inside the rows that exist
print(grid[1]) # [4, 5, 6]

That mistake raises an error like this.

Output

Traceback (most recent call last):
File "main.py", line 2, in <module>
print(grid[2])
IndexError: list index out of range

Last, forgetting the inner loop. If you loop once over a nested list, each item is a whole row, not a single value. You need the second loop to reach the values inside.

grid = [[1, 2, 3], [4, 5, 6]]
# ❌ Avoid: this prints whole rows, not single numbers
for row in grid:
print(row)
# βœ… Good: a second loop reaches each value
for row in grid:
for value in row:
print(value)

βœ… Best Practices

Small habits keep nested lists easy to read and easy to trust.

  • Put each inner list on its own line when you write a grid. It lines up like a real table and is far easier to read.
  • Name your loop variables for what they hold. for row in grid and for value in row tell the reader exactly what is going on.
  • Keep every row the same length. A grid where rows have different sizes is harder to loop over and a common source of bugs.
  • Reach for a nested list only when your data really is a grid. If it is a flat line of items, a plain list is simpler.

🧩 What You’ve Learned

You can now hold a whole grid in one variable and move around it with confidence.

  • βœ… A nested list is a list inside a list, perfect for rows and columns.
  • βœ… You build one by putting inner lists as the items of an outer list.
  • βœ… You read a single value with two indexes, grid[row][column].
  • βœ… The first index picks the row, the second picks the column.
  • βœ… A nested loop, one loop inside another, visits every value in the grid.
  • βœ… Real grids like a tic-tac-toe board or a table of marks fit this shape neatly.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What is a nested list in Python?

    Why: A nested list holds other lists as its items, which is how it represents rows and columns.

  2. 2

    For grid = [[1, 2, 3], [4, 5, 6]], what does grid[1][0] give?

    Why: grid[1] is the second row [4, 5, 6], and [0] picks its first item, which is 4.

  3. 3

    Why do you use a nested loop to print every value in a 2D list?

    Why: The outer loop takes one row at a time, and the inner loop reaches each value inside that row.

  4. 4

    What happens if you ask for grid[2] when grid has only two rows (index 0 and 1)?

    Why: Index 2 is past the last row, so Python raises IndexError: list index out of range.

πŸš€ What’s Next?

You can store and read a grid now. Next you will learn how to put a list in order, smallest to largest or A to Z, with just one line.

Sorting Lists

Share & Connect