Trying to create and alter grid, but assigning values to specific index in nested list is unexpectedly duplicated to other nested lists

(Python 3.9) I’m trying to solve a percolation problem/assignment, and just to start, I’m creating an n-by-n grid. While the grid looks correct on creation, when I try to alter a specific value inside the grid (in a nested list), it’s assigning that value to every sublist, rather than only the list I’m referencing with it’s index.

Here’s the class and relevant bits:

class Percolation:
    """Create an n-by-n grid, with all sites initially blocked."""
    def __init__(self, n):
        self.grid = self.create_grid(n)

    def create_grid(self, n):
        """ Create n-by-n grid with default 0 (blocked) values."""
        grid = []
        # Create x, rows.
        values = [0 for _ in range(n)]
        # Create y, columns.
        for _ in range(n):
            grid.append(values)
        return grid

    def show_grid(self):
        for row in self.grid:
            print(row)

size = 5
perc = Percolation(size)
# I chose 8 and 5 arbitrarily to test this issue so they're easy to spot.
perc.grid[0][2] = 8
perc.grid[1][1] = 5
perc.show_grid()

show_grid() is then showing me all sublists are changed.

>>> 
[0, 5, 8, 0, 0]
[0, 5, 8, 0, 0]
[0, 5, 8, 0, 0]
[0, 5, 8, 0, 0]
[0, 5, 8, 0, 0]

While what I was expecting is this:

>>> 
[0, 0, 8, 0, 0]
[0, 5, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]

Am I making the mistake when I create the grid by appending “values” multiple times in a loop? Or am I incorrectly referencing indexes? I thought maybe at first show_grid() was accidentally printing the same row over and over, but printing self.grid directly still shows duplicate values across all sublists, regardless of n or how I assign values.

What I do see is that when I change only a value in the main list, I do get what I expect.

perc.grid[2] = [0, 0, 8, 0, 0]
perc.show_grid()

>>>
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 8, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]

How do I properly change values in these nested lists in this case? What is actually happening when I’m setting perc.grid[0][2] = 8?

Answer

In python when you create a list and assign it to multiple places, it is the same list, not a new list with the same values. So when you create the list values and append it to grid, each nested list is actually the same list.

One way you can avoid this problem is by copying the list using an index of the entire list [:] like: grid.append(values[:])