0

Possible Duplicate:
Unexpected feature in a Python list of lists

I have a matrix filled with 0's of 9 by 11. I want to make the first element of each row and the first element of each column have a score of -2 less than the previous one, so:

[[0, -2, -4], [-2, 0, 0], [-4, 0, 0]]

For this I use the following code:

# make a matrix of length seq1_len by seq2_len filled with 0's\
x_row = [0]*(seq1_len+1)
matrix = [x_row]*(seq2_len+1)
# all 0's is okay for local and semi-local, but global needs 0, -2, -4 etc at first elmenents
# because of number problems need to make a new matrix
if align_type == 'global':
    for column in enumerate(matrix):
        print column[0]*-2
        matrix[column[0]][0] = column[0]*-2
for i in matrix:
    print i

Result:

0
-2
-4
-6
-8
-10
-12
-14
-16
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[-16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Why does it give the last value of column[0]*-2 to all the rows?

Community
  • 1
  • 1
Niek de Klein
  • 8,524
  • 20
  • 72
  • 143
  • 1
    @senderle -- Good find. This one is such a common question, but the titles are all over the place it's hard to track down a duplicate when I see it come up. – mgilson Nov 01 '12 at 12:17
  • @mgilson, it is indeed hard. All credit should go to [flebool](http://stackoverflow.com/a/13176124/577088) in this case! – senderle Nov 01 '12 at 12:18

2 Answers2

3

Try running this code:

x_row = [0]*(seq1_len+1)

matrix = [x_row]*(seq2_len+1)

matrix[4][5]=5

print matrix

you see that the 5 has spread. This happened because the second line of code replicates the same data. see this

List of lists changes reflected across sublists unexpectedly

Community
  • 1
  • 1
gg349
  • 21,996
  • 5
  • 54
  • 64
1

It's because the way you're creating the list of lists actully produces a list that contain same list object in it, i.e same id(), changing one actually changes others as well:

In [4]: x_row = [0]*(5+1)

In [5]: matrix = [x_row]*(7+1)

In [6]: [id(x) for x in matrix]
Out[6]:                         #same id()'s, means all are same object
[172797804,
 172797804,
 172797804,
 172797804,
 172797804,
 172797804,
 172797804,
 172797804]

In [20]: matrix[0][1]=5 #changed only one

In [21]: matrix         #but it changed all
Out[21]: 
[[0, 5, 0, 0, 0, 0],
 [0, 5, 0, 0, 0, 0],
 [0, 5, 0, 0, 0, 0],
 [0, 5, 0, 0, 0, 0],
 [0, 5, 0, 0, 0, 0],
 [0, 5, 0, 0, 0, 0],
 [0, 5, 0, 0, 0, 0],
 [0, 5, 0, 0, 0, 0]]

you should create your matrix this way to avoid that:

In [12]: matrix=[[0]*6 for _ in range(9)]

In [13]: [id(x) for x in matrix]
Out[13]:                           #different id()'s, so different objects 
[172796428,              
 172796812,
 172796364,
 172796268,
 172796204,
 172796140,
 172796076,
 172795980,
 172795916]

In [23]: matrix[0][1]=5  #changed only one

In [24]: matrix         #results as expected
Out[24]: 
[[0, 5, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0]]
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504