List being reassigned new values when not explicitly told to do so

时间:2015-08-07 02:35:09

标签: python macos list

I am writing a program that dose many math computations that eventually make a list of points to plot. I does so over several iterations and gets one point per iteration, and then uses the new point for the next iteration in the code. The list conditions_old holds the values from the last iteration. The list conditions_new are the new points that are found after an iteration is finished. At the end of the code, the lists are set equal to each other: conditions_old = conditions_new. This is the only time conditions_old is assigned a value except for the initial conditions that are used to start the calculations. With all that said, here is the problem I'm having:

conditions_old = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

kCompute = conditions_old[:]

for i in range(3):
    for j in range(3):
        print("conditions_old BEFORE: ", conditions_old[i][j])
        kCompute[i][j] = (conditions_old[i][j] + (1/4))  # This is where things get fishy.
        print("conditions_old AFTER: ", conditions_old[i][j])
        print("kCompute: ", kCompute[i][j])

This is a small portion of my code. What happens is that the list conditions_old will acquire the values of kCompute once that calculation has been made. My question is this; why is conditions_old acquiring the the new value of kCompute? Also, how do you fix this problem?

I've seen python do some odd things before, but this is something I never expected to run into.

I'm currently using python 3.4 on Yosemite

2 个答案:

答案 0 :(得分:1)

Note that:

kCompute = conditions_old[:]

makes a shallow copy. In your line:

kCompute[i][j] = (conditions_old[i][j] + (1/4))  # This is where things get fishy.

You're setting the value on one of the inner lists which is shared with conditions_old due to the shallow nature of your copy. In other words:

kCompute is conditions_old  # False
kCompute[0] is conditions_old[0]  # True

The easiest fix is to do a deep copy:

from copy import deepcopy

...
kCompute = copy.deepcopy(conditions_old)

答案 1 :(得分:1)

You need to make a deep copy of the original list before it has been edited.

kCompute = conditions_old[:] only makes a shallow copy, this the lists within the two lists, reference the same objects.

You can make a deep copy to avoid this issue:

from copy import deepcopy
kCompute = deepcopy(conditions_old)

From the docs:

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.