0

The Issue

I have a function legalMove(array, int) that is meant to take in a 15 problem's current state in the form of an array and then make a move based on a numerical command. For some reason, this function is mutating the array that I put into the array spot. Why is this and how can I fix the issue? I thought that variables within functions would remain local to that function, and would only be able to change the program level variable if I put in a line like currentState = legalMove(currentState, command)

Code

Suggested array input: currentState = [8,13,1,4,2,14,0,5,3,12,10,7,11,6,9,15]

def legalMove(currentBoard, cmd):
    #First, do the move
    #0 = UP
    #1 = RIGHT
    #2 = LEFT
    #3 = DOWN
    blankPOS = currentBoard.index(0)

    if cmd == 0: #go up
        try:
            exchangePOS = blankPOS - 4
            numberE = currentBoard[exchangePOS]

            # do the switch
            currentBoard[exchangePOS] = 0
            currentBoard[blankPOS] = numberE
        except:
            return False

    if cmd == 1: #go right
        try:
            exchangePOS = blankPOS + 1
            numberE = currentBoard[exchangePOS]

            # do the switch
            currentBoard[exchangePOS] = 0
            currentBoard[blankPOS] = numberE
        except:
            return False

    if cmd == 2: #go left
        try:
            exchangePOS = blankPOS - 1
            numberE = currentBoard[exchangePOS]
            print "blanksPOS",blankPOS
            print "exchangePOS",exchangePOS
            print "currentBoard[blankPOS]",currentBoard[blankPOS]
            print "currentBoard[exchangePOS]",currentBoard[exchangePOS]

            # do the switch
            currentBoard[exchangePOS] = 0
            currentBoard[blankPOS] = numberE
        except:
            return False

    if cmd == 3: #go down
        try:
            exchangePOS = blankPOS + 4
            numberE = currentBoard[exchangePOS]

            # do the switch
            currentBoard[exchangePOS] = 0
            currentBoard[blankPOS] = numberE
        except:
            return False

    return currentBoard
xxmbabanexx
  • 8,256
  • 16
  • 40
  • 60
  • The question is less about the code you show and more about how function arguments are passed in Python in general. I encourage you to read up on how pass-by-reference works. – Tomalak Apr 25 '17 at 13:34
  • 1
    Possible duplicate of [How do I pass a variable by reference?](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) – Tomalak Apr 25 '17 at 13:34
  • If you don't want to alter the original array, copy it and work on the copy. – khelwood Apr 25 '17 at 13:35
  • When you call `legalMove(currentState[:], cmd)`, that will pass a copy of the list rather than a reference to the original. – cdarke Apr 25 '17 at 13:36
  • or represent the state in a tuple, which you can't modify, but you can use it as a dict key. Instead of modifying, you create the new state. – Kenny Ostrom Apr 25 '17 at 13:50

1 Answers1

3

I thought that variables within functions would remain local to that function

Half true. Variables that being created inside a function, are visible and alive only during the execution of the function and cannot be accessed from any outer scope, and not available after the function finished to execute.

However, in Python, all objects, especially lists, that being passed to functions are passed by reference, which means that a change in the function would cause a change in the object in other places.

Example:

>>> l = [1, 2, 3, 4]
>>> def func(some_list):
...   some_list.append(5)
... 
>>> func(l)
>>> l
[1, 2, 3, 4, 5]

In order to avoid this situation, you would need to pass to the function a copy of that list (so basically create a new object that will not affect the original list when changing it inside the function).

You can achieve that by using the list() literal when passing the list to the function.

Example:

>>> l = [1, 2, 3, 4]
>>> def func(some_list):
...   some_list.append(5)
... 
>>> func(list(l))
>>> l
[1, 2, 3, 4]
>>> 
Avihoo Mamka
  • 4,656
  • 3
  • 31
  • 44