0

I have a really weird issue in Python3. I have some code that generates some different list from a list of integers (what this does exactly is not relevant).

def get_next_state(state):

    max_val = max(state)
    max_index = state.index(max_val)
    new_state = state

    for n in range(max_val + 1):
        new_state[max_index] -= 1
        new_state[(n + max_index) % len(state)] += 1

    return new_state

Now all I want to do is add a next state to some list that keeps the states. This is my code:

l = [0, 2, 7, 0]
seen_states = []

for _ in range(10):
    print(l)
    seen_states += [l]
    l = get_next_state(l)

print(seen_states)

For some reason list l is assigned correctly when I print it, but it is not added correctly to the list of seen states. Note that I have also tried seen_states.append(l) instead of using += [l]. Does anyone know why this happend?

2 Answers2

0

Using new_state = state[:] (copies the list instead of referencing the original) in the get_next_state produces the following output:

[0, 2, 7, 0]
[2, 4, 1, 2]
[3, 1, 2, 3]
[0, 2, 3, 4]
[1, 3, 4, 1]
[2, 4, 1, 2]
[3, 1, 2, 3]
[0, 2, 3, 4]
[1, 3, 4, 1]
[2, 4, 1, 2]
[[0, 2, 7, 0], [2, 4, 1, 2], [3, 1, 2, 3], [0, 2, 3, 4], [1, 3, 4, 1], [2, 4, 1, 2], [3, 1, 2, 3], [0, 2, 3, 4], [1, 3, 4, 1], [2, 4, 1, 2]]

Not sure if this is your desired output, as you did not specify what you are getting as "wrong" output

lkriener
  • 187
  • 2
  • 7
  • Thanks! That was indeed the desired output. Do you know why leaving out the `[:]` in the statement: `new_state = state[:]` produces a wrong output? – Michiel Boswijk Dec 07 '17 at 17:40
  • You can look at this https://stackoverflow.com/a/17246744/8512629 it is a nice explanation on assignement vs deep and shallow copies – lkriener Dec 07 '17 at 17:43
0

To prevent these problems use copy, deepcopy or list[:]

import copy

def get_next_state(state):

    max_val = max(state)
    max_index = state.index(max_val)
    new_state = copy.deepcopy(state)

    for n in range(max_val + 1):
        new_state[max_index] -= 1
        new_state[(n + max_index) % len(state)] += 1

    return new_state

You are sending your list l inside the function. When you assign it to another name, you are not making a copy but referencing the original object. Any modification on these lists is a change in the original object.

joaquin
  • 82,968
  • 29
  • 138
  • 152