-1

I am trying to write some code, where in it i need to fill in a matrix and make it the identity matrix and i decided to make this matrix a list of n lists, where each nth list is a row.

I=[]

row=[]

for i in range (0,n):
    row.append(0)

for i in range (0,n):
    I.append(row)

for k in range (0,3):   
    I[k][k]=1

I expected this code to put 1's in the matrix's diagonal, where the diagonal are the I[k][k] elements, k=0,1,2. But in the 3rd for loop, where i am replacing the 0's in the diagonal by 1's, in each step, instead of making I[k][k]=1 it makes I[0][k]=I[1][k]=I[2][k]=1 and I end up with a matrix with every element equal to 1.

My question is not how to make a identity matrix in python, or any matrix, my question is, why is the 3rd for loop doing that, clearly I[k][k] are diagonal elements, why is it making other non diagonal elements equal to 1?

rdas
  • 20,604
  • 6
  • 33
  • 46
orochi
  • 143
  • 5
  • You have only one data item. You add its reference three times to youzr list. If you change the data through one reference, the others still reference the same data. See the second dupe how to clone a list correctly. – Patrick Artner Apr 13 '19 at 20:52
  • Constrcut `I` with `I = [[0 for j in range(n)] for i in range(n)] `. Then you can set the 1s with the last iteration. – hpaulj Apr 13 '19 at 20:55

2 Answers2

1

You can nest your for loops when creating the matrix and use the second loop to fill the row and when i is equal to j, then you are in the diagonal of the matrix:

matrix = []
n = 10

for i in range(0, n):
    row = []

    for j in range(0, n):
        if i == j:
            row.append(1)
        else:
            row.append(0)

    matrix.append(row)
Omari Celestine
  • 1,405
  • 1
  • 11
  • 21
1

Great question! In Python, the variables are pointers so what is going on is each element of I is pointing to the same row variable. Thus, when you change an element in one row of I, you are really changing it in all of the rows.

Here is an example:

n = 3
row = []
for i in range(n):
    row.append(0)

I = []
for i in range(n):
    I.append(row)

Now, let's try to set the first element of the first row to 1, I[0][0] = 1, but in reality this produces [[1, 0, 0], [1, 0, 0], [1, 0, 0]].

Finally, to answer your question, even though you are only setting the diagonal entries of I, it is really setting all of the elements of I because each row is the same in memory. Omari Celestine's answer works because it allocates a new section of memory for each row rather than just one section of memory.

colelemonz
  • 1,229
  • 1
  • 15
  • 27