0

I wrote a simple python script that creates a 7x7 list of dots '.', I want to change the diagonal to stars '*'.
Here is my script
n=7
l=['.']*n
m=[l]*n
for i in range(n):
    for j in range(n):
        if i==j:
            m[i][j]='*'
    print(*m[i])

Here is the output I get

* . . . . . .
* * . . . . .
* * * . . . .
* * * * . . .
* * * * * . .
* * * * * * .
* * * * * * *

I don't understand why I have such output, when I added an else statement it works fine.
Did I miss something ?

Celius Stingher
  • 17,835
  • 6
  • 23
  • 53
user3733333
  • 161
  • 1
  • 2
  • 7

2 Answers2

2

It's not because of the if condition not working, but this m = [l] * n creates an array of size n, with all being the same copy of the array l, like [l, l, l, l, l, l, l]

You can see what I am saying with this script:

l=['.']*n
m=[l]*n
m[1][1] = '*'

m is now:

[
  ['.', '*', '.', '.', '.', '.', '.'], 
  ['.', '*', '.', '.', '.', '.', '.'], 
  ['.', '*', '.', '.', '.', '.', '.'], 
  ['.', '*', '.', '.', '.', '.', '.'], 
  ['.', '*', '.', '.', '.', '.', '.'], 
  ['.', '*', '.', '.', '.', '.', '.'], 
  ['.', '*', '.', '.', '.', '.', '.']
]

What you can do is something like:

m = [ ['.'] * n for i in range(n) ]

Like this, m does not have references of same array. Therefore you can safely mutate any elements without affecting other rows:

n = 7
m = [ ['.'] * n for i in range(n) ]

for i in range(n):
    for j in range(n):
        if i==j:
            m[i][j]='*'
    print(*m[i])

outputs:

* . . . . . .
. * . . . . .
. . * . . . .
. . . * . . .
. . . . * . .
. . . . . * .
. . . . . . *
AdmiJW
  • 83
  • 6
  • I had identified the issue but was not able to think of the way to fix it. is there any alternative for this like using l[::], I can use this only for making copy of l not able to use in this case – Nikhil Belure Nov 14 '22 at 11:10
0

It's because m consist of n references to l list.

So when you're modyfing m[i][j] = '*' you're constantly replacing consecutive . with * in the same list.

Here's sample which will help you understand this problem:

>>> l = [1, 2, 3]
>>> l1 = l
>>> l2 = l.copy()
>>> l1[0] = None
>>> l2[1] = None
>>> l
[None, 2, 3]
>>> l1
[None, 2, 3]
>>> l2
[1, None, 3]

You can fix your code by replacing m = [l] * n with m = [l.copy() for _ in range(n).

Jakub Kuszneruk
  • 1,188
  • 1
  • 12
  • 37