Home > Blockchain >  Why doesn't the "if" condtion work properly alone in this python script?
Why doesn't the "if" condtion work properly alone in this python script?

Time:11-14


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).

  • Related