Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function in Python Setting Global Variables (without intent)

I don't know if this is a problem that others get, but I have code in python that goes like this:

def makemove(board,move,val):
    new=board
    new[move[0]][move[1]]=val
    return new

My problem is that if I use this function by simply doing makemove(game,[0,1],-1) where game equals [[0,0,1],[0,1,0],[1,0,0]] the variable game becomes [[0, -1, 1], [0, 1, 0], [1, 0, 0]].

I have tried to look into functions setting global variables, but I have thus for not found a way to prevent makemove() from setting the variables that you put into it. Is there something obvious that I'm missing?

like image 543
Nathan Eaves Avatar asked May 23 '26 04:05

Nathan Eaves


2 Answers

You need to clone board.

import
new = copy.deepcopy(board)

see https://stackoverflow.com/a/2612815/93910 for other ways of doing this.

Your code sets elements of a variable which is a "reference". In other words, your variable new is really an array reference to board, i.e. it points to the same memory location. So when you change new, the original variable board gets changed.

Here's another answer on how to think about this: https://stackoverflow.com/a/9697367/93910

like image 134
Sanjay Manohar Avatar answered May 24 '26 21:05

Sanjay Manohar


This is basically because assignment in Python doesn't mean what you think it does, and lists are mutable sequences.

Lists are Python objects. The name board is merely a label for or reference to that object. So when you say new=board this means "let the name new reference the same object as the name board".

In Python every object has a unique identifier that you can retrieve using id(). Let's create a board, do the assignment and see what happens:

In [1]: board = [[0,0,1],[0,1,0],[1,0,0]]

In [2]: new = board

In [3]: id(new), id(board)
Out[3]: (34495504136, 34495504136)

new and board are referencing the same object.

Since a list is a mutable sequence you can change it without getting an error.

So if you want to play with any mutable sequence inside a function without modifying the original, you should use copy.deepcopy first to make a copy and modify that.

like image 27
Roland Smith Avatar answered May 24 '26 21:05

Roland Smith