0

I have written a class to produce and manipulate a multi-dimensional list which represents a 9 x 9 grid. I have a method which produces this list. The list seems to be produced fine, but when I try to append to a specific index, it appends to all the lists.

class Grid:
    def __init__(self):
        self.size = range(9)
        self.grid = self.make_new_grid([])

    def make_new_grid(self, contents):
        grid = []
        for row in self.size:
            grid.append([])
            for column in self.size:
                grid[row].append(contents)
        return grid

grid = Grid()
grid.grid[4][5].append(8)
print('class grid', grid.grid)

Output:

class grid [[[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]], [[8], [8], [8], [8], [8], [8], [8], [8], [8]]]

To test this, I hardcoded the same grid and did the same. The output I got was as expected.

compare_grid = [[[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []]]
compare_grid[4][5].append(8)
print(compare_grid)

Output:

comparison grid [[[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [8], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []], [[], [], [], [], [], [], [], [], []]]

Finally I tested whether the grid produced by the class and my hardcoded grid were equal:

grid = Grid()
compare_grid = [[[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []],
                [[], [], [], [], [], [], [], [], []]]
print(grid.grid==compare_grid)

Output:

True

I have tried to figure this problem out for a while but I can't seem to find the answer.

martineau
  • 119,623
  • 25
  • 170
  • 301

2 Answers2

0

You keep appending the same object as the inner list:

grid[row].append(contents)

So of course, when you append to that list, which is the only distinct object inside the outer list, the changes are seen everywhere.

You can append a copy to fix this:

grid[row].append(contents.copy())
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • Of course! Thank you. Because when an object is assigned another object, it doesn't make a copy, just relabels it. Should have figured out that was the problem earlier. – Sulaiman Amjad Jan 02 '19 at 09:32
0

What is happening is more or less this (it should be self explanatory):

l1 = []
l2 = l1
l2.append(1) # <-- note l2
print(l1) # <-- note l1
#=> [1, 2, 3, 4]

To solve the problem it is required to copy the "content" of the object and not the object itself, for example:

l2 = l1[:]

But here you can find a lot more: How to clone or copy a list?

In your case, you could change your method to:

def make_new_grid(self, contents = []):
    return [[ contents[:] for col in self.size ] for row in self.size]
iGian
  • 11,023
  • 3
  • 21
  • 36