How do I not mutate nested lists in Python?

My code:

 class World:
    def __init__(self, _map, pos):
        self.orig_map = _map
        self.map = self.orig_map[:]
        self.orig_pos = pos
        self.pos = list(self.orig_pos)
    def reset(self):
        self.map = self.orig_map[:]
        self.pos = list(self.orig_pos)
    def left(self):
        if self.pos[1]>0:
            self.pos[1]-=1
    def right(self):
        if not self.pos[1]+1>=len(self.map[0]):
            self.pos[1]+=1
    def up(self):
        if self.pos[0]>0:
            self.pos[0]-=1
    def down(self):
        if not self.pos[0]+1>=len(self.map):
            self.pos[0]+=1
    def eat(self):
        if self.map[self.pos[0]][self.pos[1]]==1:
            self.map[self.pos[0]][self.pos[1]]=0
            return True

      

What is going to happen:

>>> w=World([[0,0,0],[0,1,0],[0,0,0]],(0,0))
>>> w.right()
>>> w.down()
>>> w.eat()
True
>>> w.reset()
>>> w.map
>>> [[0, 0, 0], [0, 1, 0], [0, 0, 0]]

      

What's happening:

>>> w=World([[0,0,0],[0,1,0],[0,0,0]],(0,0))
>>> w.right()
>>> w.down()
>>> w.eat()
True
>>> w.reset()
>>> w.map
>>> [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

      

Where it probably goes wrong: self.map = self.orig_map[:]

The above could work (tested and tested) for a single list, however it doesn't work for nested lists.

+3


source to share


2 answers


When self.map = self.orig_map[:]

you say you are actually making a copy self.orig_map

. However, this is a shallow copy, and the elements inside self.map

will be all the same objects as the elements inside self.orig_map

.

Instead, you need to make a self.map

deep copy self.orig_map

in __init__

. For example.



import copy
...
    self.map = copy.deepcopy(self.orig_map)

      

+5


source


You must use deepcopy

import copy

cop2 = copy.deepcopy(origin) 

      



It will copy your object recursively.

+4


source







All Articles