Python assignment

Hi,

I wonder why I get this output:

s = {(3,1)}
n = 4
m = 4
test = [['X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X']]
for k in list(s):
    test[k[0]][k[1]] = 'O'
print(test)
test[:] = [['A']*n]*m
for k in list(s):
    test[k[0]][k[1]] = 'O'
print(test)

Output:

[['X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X'], ['X', 'O', 'X', 'X']]
[['A', 'O', 'A', 'A'], ['A', 'O', 'A', 'A'], ['A', 'O', 'A', 'A'], ['A', 'O', 'A', 'A']]

I understand the first output, but not the second. How may I make my second output like the first?

[['A', 'A', 'A', 'A'], ['A', 'A', 'A', 'A'], ['A', 'A', 'A', 'A'], ['A', 'O', 'A', 'A']]

When I try to run your code, I get an error:

NameError: name 's' is not defined

We can’t really help you effectively if we can’t run your code.

But in this case, I may be able to guess. You have:

test[:] = [['A']*n]*m

That creates a single list [‘A’, ‘A’, ‘A’, ‘A’], and then replicates it three more times in a second list.

The same as this:

L = ['A']*4  # like ['A', 'A', 'A', 'A']
test = [L, L, L, L]

So your test list has the same list in it four times. When you modify the list, the change shows up four times, because they are the same list!

Not four independent lists which happen to start off equal, but the same list repeated four times.

You should do this instead:

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

which creates m distinct lists, each of which is initialised to ['A']*n.

(By the way, you probably don’t need the slice assignment test[:] = ... here.)

1 Like

Sorry. I have just edited the original post.

s = {(3,1)}
n = 4
m = 4

Thank you very much for your reply. I still want to know a little more about the mechanism of the Python compiler in order to avoid the next pitfall.
As you say, if we do this

b = [[None]*2]*3
b
[[None, None], [None, None], [None, None]]
b[1][0] = 2
b
[[2, None], [2, None], [2, None]]

However, I do not have any problem when repeating the same value:

a = [None]*3
a
[None, None, None]
a[2] = 5
a
[None, None, 5]

What’s the difference? When I can repeat a “number” several times in a list, it would be ok if I overwrite one of them.Others will not be affected. I won’t get [5,5,5] in this case. However, when I repeat a “list” several times and overwrite one of them, then other copies will also be affected as well. Is it a difference between two data type – a single number and a list? Thank you!!

By John M via Discussions on Python.org at 21Mar2022 06:01:

Thank you very much for your reply. I still want to know a little more
about the mechanism of the Python compiler in order to avoid the next
pitfall.
As you say, if we do this

b = [[None]*2]*3
b
[[None, None], [None, None], [None, None]]
b[1][0] = 2
b
[[2, None], [2, None], [2, None]]

However, I do not have any problem when repeating the same value:

a = [None]*3
a
[None, None, None]
a[2] = 5
a
[None, None, 5]

What’s the difference? When I can repeat a “number” several times in a
list, it would be ok if I overwrite one of them. Others will not be
affected. However, when I repeat a “list” several times and overwrite
one of them, then other copies will also be affected as well. Is it a
difference between two data type – a single number and a list? Thank
you!!

It isn’t a difference between the data types (except in that lists have
an internal structure - their elements).

When you do this:

b = [[None]*2]*3

a few things happen in sequence:

  • a single element list [None] is made, let’s call that list1
  • a 2-element list [None,None] is made by doubling list1, let’s call
    that list2

Before we go further, remember that all Python variables hold references
to objects. So [None] has a single reference to the None object.

list2 being [None,None] has 2 references to the same None
objects. We made it by making a list with list1's references repeated
twice.

After list2 (which was [None,None]), we made [list2] (because it
came from [None]*2). So that is a single element list with a single
reference to list2.

Then you compute:

b = [[None]*2]*3

which is:

b = [list2] * 3

That makes a 3 element list containing 3 references, all to the same
list2 object.

So when you do this:

b[1][0] = 2

you’re modifying list2[0]. When you display b you see list2 three
times, because there are 3 references.

Cheers,
Cameron Simpson cs@cskk.id.au