list assignment using concatenation "*"

L

liquid

If I do:

a = [ [0,0,0], [0,0,0], [0,0,0] ]
a[0][1] = 1

I get:

a = [ [0,1,0],[0,0,0],[0,0,0] ]

as expected

But if I do:

a = [ [0] * 3 ] * 3
a[0][1] = 1

I get

a = [[0,1,0],[0,1,0],[0,1,0]]

AFAIC, "*" is supposed to generate multiple copies of the given token.
Therefore I thought both cases would be the same, but they are not.

Can anyone explain to me what exactly is going on in the second case?
 
S

Steve R. Hastings

if I do:
a = [ [0] * 3 ] * 3
a[0][1] = 1

I get

a = [[0,1,0],[0,1,0],[0,1,0]]

The language reference calls '*' the "repetition" operator. It's not
making copies of what it repeats, it is repeating it.

Consider the following code:
a = []
b = []
a == b True
a is b False

a = b = []
a is b True
a.append(1)
a [1]
b
[1]


Each time you use [], you are creating a new list. So the first code sets
a and b to two different new lists.

The second one, "a = b = []", only creates a single list, and binds both a
and b to that same list.

In your example, first you create a list containing [0, 0, 0]; then you
repeat the same list three times.
a = [[0]*3]*3
a [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
a[0] is a[1] True
a[0] is a[2]
True

When you run [0]*3 you are repeating 0 three times. But 0 is not mutable.
When you modify a[0] to some new value, you are replacing a reference to
the immutable 0 with some new reference. Thus, [0]*3 is a safe way to
create a list of three 0 values.

When you have a list that contains three references to the same mutable,
and you change the mutable, you get the results you discovered.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,285
Messages
2,571,416
Members
48,107
Latest member
AmeliaAmad

Latest Threads

Top