I create a list from another one but the changes in one affect me both ... What do I do wrong?

1

I am a pithon enthusiast and self-taught and I find myself with the following problem: In a method I create a list from another one where I have to make some changes within a loop, to each cycle I want the second created list to be copied from the first in the state it was in, but the changes I made in this also affect the first. Specifically it is a minimap where I represent the position of a character in movement, but instead of a point with the current position I draw a line ... I do not know what I do wrong. The part of the code where the problem is is as follows (I use python 3.4 and pygame 1.9.2):

# Crea una matriz con el mapa.
def matrizar_minimapa(self):
       # lista que creo a partir de self.matriz_mapa que quiero 
       # que se quede intacta
    matriz = [] 
    matriz.extend(self.matriz_mapa)  
    for element in self.elements.values():
        f,c = self.buscarPos(element.map_pos)

        # Esto me modifica las dos listas ¡¿?!
        matriz[f][c] = 2   

# crea una superficie minimapa donde se representa el mapa y elementos
def get_minimapa(self):
    celwidth = 3
    minimap_w = len(self.matriz_mapa)*celwidth
    minimap_h = len(self.matriz_mapa[0])*celwidth
    matriz = self.matrizar_minimapa()

    pisable     = pygame.image.load('utilidades/imagenes/minimapa/pisable.png')
    nopisable   = pygame.image.load('utilidades/imagenes/minimapa/nopisable.png')
    elemento    = pygame.image.load('utilidades/imagenes/minimapa/elemento.png')
    foco        = pygame.image.load('utilidades/imagenes/minimapa/foco.png')

    minimap_surface = pygame.Surface((minimap_w, minimap_h))
    x = 0
    y = 0
    for f in matriz:
        for c in f:
            if c == 0:
                minimap_surface.blit(pisable, (x,y))
            elif c == 1:
                minimap_surface.blit(nopisable, (x,y))
            elif c == 2:
                minimap_surface.blit(elemento, (x,y))
            x += celwidth
        y += celwidth
        x = 0

    minimap_surface.convert_alpha()
    return minimap_surface

For what it's worth, the variable I want to leave intact (which represents the map) I think of it as follows:

    # Crea una matriz con el mapa donde 0 es pisable y 1 no.
def matrizar_mapa(self, mapa_nopisable, mapasize):
    matriz = []
    width = 22
    fil = 0

    for y in range(0, mapasize[0], width):
        matriz.append([])
        for x in range (0, mapasize[1], width):
            cel = pygame.Rect(x, y, width, width)
            if cel.collidelist(mapa_nopisable) == -1:
                matriz[fil].append(0)
            else:
                matriz[fil].append(1)
        fil += 1

    self.matriz_mapa = matriz
    
asked by BigfooTsp 24.02.2017 в 18:29
source

1 answer

1

The list you intend to duplicate is a "list of lists" . Even if you create a new list, each element of the new list is created from the original lists.

For clarification, suppose the following code:

lst1 = [[0,1,2],[3,4,5]]
lst2 = []
lst2.extend(lst1)
lst2.append(6)

print(lst1)  # -> [[0,1,2],[3,4,5]]
print(lst2)  # -> [[0,1,2],[3,4,5],6]

By adding the list lst1 to lst2 , the same elements that had lst1 are added, they are not duplicated.

The lists that make up the first list must also be duplicated. The simple (and usual) way is to use the operator slice [:] without arguments, applied to each of the lists:

lst2 = [l[:] for l in lst1]

For your case, we know that you only have one level of nested lists and that it works just as I put it. But in a more general case we could use the deepcopy function to be more secure:

from copy import deepcopy

lst2 = deepcopy(lst1)
    
answered by 24.02.2017 в 23:41