1

I'm working on a simple version of Conway's Game of Life. When I input something such as 0001, the output should be 1010. The program handles the 1's and 0's as bools.

In the code snippet below, I'm printing the 'copy' variable, which should only change once per generation. Instead, it's changing every time the for loop loops. Why is 'copy' changing? Shouldn't 'state' be the only thing that's changing?

def adj(state,i):
    a = b = False
    if i == 0: #checking on left wall
        a = state[-1]
        b = state[i+1]
    elif i == len(state)-1: #checking on right wall
        a = state[i-1]
        b = state[0]
    else: #checking in the middle
        a = state[i-1]
        b = state[i+1]
    return [a,b].count(True)

def evolve(state):
    copy = state #changes are made to state based on the copy
    for i in range(len(copy)):
        print(copy)
        if adj(copy,i) == 1:
            state[i] = True
        else:
            state[i] = False
    return state
Will Da Silva
  • 6,386
  • 2
  • 27
  • 52
  • you set copy = state, so that means both variables point to the same value. Maybe what you want is copy = copy.copy(state) – Joseph James Feb 18 '16 at 16:36
  • Read this for a better understanding of *why* `copy = state` does not make a copy. http://nedbatchelder.com/text/names1.html – chepner Feb 18 '16 at 16:51
  • You can also read the accepted answer on this SO question about trying to do the inverse: http://stackoverflow.com/questions/13538266/python-copy-of-a-variable – neerajt Feb 18 '16 at 17:09

2 Answers2

3

This line of code:

copy = state

does not make a separate copy of 'state'. 'copy' and 'state' now refer to the SAME list object.

If you want a separate copy, use slicing instead:

copy = state[:]
John Gordon
  • 29,573
  • 7
  • 33
  • 58
2

copy and state are both names for the same object. That object (probably a list) happens to have a __setitem__ method, through which you mutate it.

Demo:

>>> state = [1,2,3]
>>> copy = state
>>> state[2] = 42
>>> copy
[1, 2, 42]
>>> state
[1, 2, 42]

If you want your copy to actually be a name for a copy of state, you need a copy of state.

>>> state = [1,2,3]
>>> copy = state[:] # make a shallow copy of state
>>> state[2] = 42
>>> copy
[1, 2, 3]
>>> state
[1, 2, 42]
timgeb
  • 76,762
  • 20
  • 123
  • 145