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
``````

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.

``````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