Unexpected behavior in nested for loop in python

Very simple code nested example:

All the code does is create a list of lists that is initialized to zero. It iterates through the list rows and columns and each position is given a value. For some reason the last row of the 2D list is duplicated for each row when the final vector is printed.

Number_of_channels=2
Coefficients_per_channel=3

coefficient_array=[[0]*Coefficients_per_channel]*Number_of_channels 
print coefficient_array

for channel in range(Number_of_channels):
    for coeff in range(Coefficients_per_channel):
        coefficient_array[channel][coeff]=coeff*channel
        print coefficient_array[channel][coeff]

print coefficient_array

Output:

[[0, 0, 0], [0, 0, 0]]
0
0
0
0
1
2
[[0, 1, 2], [0, 1, 2]]

I actually expect:

[[0, 0, 0], [0, 1, 2]]

Anyone have any idea how come this is happening?

Answers


You only duplicate the outer list, but the values of that list are left untouched. Thus, all (both) outer lists contain references to the same inner, mutable list.

>>> example = [[1, 2, 3]]
>>> example *= 2
>>> example
[[1, 2, 3], [1, 2, 3]]
>>> example[0][0] = 5
[[5, 2, 3], [5, 2, 3]]
>>> example[0] is example[1]
True

Better create the inner lists in a loop:

coefficient_array=[[0]*Coefficients_per_channel for i in xrange(Number_of_channels)]

or, illustrated with the python prompt again:

>>> example = [[i, i, i] for i in xrange(2)]
>>> example
[[0, 0, 0], [1, 1, 1]]
>>> example[0][0] = 5
>>> example
[[5, 0, 0], [1, 1, 1]]
>>> example[0] is example[1]
False

With

coefficient_array=[[0]*Coefficients_per_channel]*Number_of_channels

you do a duplication of references to the same object:

coefficient_array[0] is coefficient_array[1]

evaluates to True.

Instead, build your array with

[[coeff*channel for coeff in range(Coefficients_per_channel)] for channel in range(Number_of_channels)]

Try this instead:

coefficient_array=[0]*Number_of_channels 
print coefficient_array

for channel in range(Number_of_channels):
    coefficient_array[channel] = [0] * Coefficients_per_channel
    for coeff in range(Coefficients_per_channel):
        coefficient_array[channel][coeff]=coeff*channel
        print (channel, coeff)
        print coefficient_array[channel][coeff]

print coefficient_array

Need Your Help

How do you set up a relationship between properties of two angular controllers?

angularjs

Say I've got AdamController as adam and AnujController as anuj. I want anuj.anujProp to have a j appended to it every time adam.adamProp changes.

Force the read() method to read a minimum no of characters

java telnet bufferedreader expect

I am trying to do telnet to a router with expect kind of implementation.