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 ?
CodePudding user response:
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:
* . . . . . .
. * . . . . .
. . * . . . .
. . . * . . .
. . . . * . .
. . . . . * .
. . . . . . *
CodePudding user response:
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)
.