user7479988
user7479988

Reputation: 23

How to prevent function from modifying list?

The list that I pass to the function as "puzzle" is being modified, and I want the function to keep it the same.

"""moveDown() works by swapping the empty space with the block above it."""
def moveDown(xPosition, yPosition, puzzle):
    returnPuzzle = list()
    returnPuzzle.append(puzzle)
    returnPuzzle = returnPuzzle[0]

    if(puzzle[yPosition][xPosition]!=0):  # is space we are moving the block into not empty?
        return -1
    if(yPosition-1<0):
        return -1

    print puzzle
    #swap
    returnPuzzle[yPosition][xPosition] = returnPuzzle[yPosition-1][xPosition]
    returnPuzzle[yPosition-1][xPosition]   = 0
    print puzzle

    return returnPuzzle

The first print statement returns the original puzzle that was passed to the function, but the second has modified it as though it was working on returnPuzzle instead of puzzle. Any idea why?

First print: [[2, 1, 3], [6, 4, 5], [8, 7, 0]]

Second print: [[2, 1, 3], [6, 4, 0], [8, 7, 5]]

Upvotes: 1

Views: 3213

Answers (3)

erbridge
erbridge

Reputation: 1386

Since puzzle is a 2d list, you need to construct a copy of it to avoid references to the inner list being kept during the copy.

def duplicate2dList(oldList):
    newList = []

    for l in oldList:
        newList.append(l[:])

    return newList

Upvotes: 0

Haldean Brown
Haldean Brown

Reputation: 12721

As the other answers have stated, you're just assigning puzzle to returnPuzzle. Because it's a nested list, you need to make what's called a "deep copy"; the other answers are referring to a shallow copy, where you copy the list but the items in the list are still the same. That means that you end up with a new outer list containing the same inner lists. Since you're mutating the inner lists, you want a copy of those as well.

The easiest way to do this is with the copy module:

import copy
def moveDown(xPosition, yPosition, puzzle):
    returnPuzzle = copy.deepcopy(puzzle)

Upvotes: 3

jasonharper
jasonharper

Reputation: 9597

returnPuzzle = list()
returnPuzzle.append(puzzle)
returnPuzzle = returnPuzzle[0]

So you create a list, append a value to it, and then retrieve that value from the list - this has NO effect whatsoever, it's exactly the same thing as accessing puzzle directly. To make a copy that you can modify without affecting the original list, use:

returnPuzzle = puzzle[:]

(that's a list slice, using the default values of the start and end of the list.)

Upvotes: 2

Related Questions