0

I had recently visited the question List of lists changes reflected across sublists unexpectedly

After seeing it, I decided to try out and experiment with the things I found there to understand how it worked in general, but I've ran into a confusing issue that has left me stumped and confused.

Here is the code:

x = [1]*4
y = x*2
print(x,y) #[1, 1, 1, 1] [1, 1, 1, 1, 1, 1, 1, 1]
x[0] = 7
print(x,y) #[7, 1, 1, 1] [1, 1, 1, 1, 1, 1, 1, 1]

x = [1]*4
y = [x]*2
print(x,y) #[1, 1, 1, 1] [[1, 1, 1, 1], [1, 1, 1, 1]]
x[0] = 7
print(x,y) #[7, 1, 1, 1] [[7, 1, 1, 1], [7, 1, 1, 1]]

Essentially, the elements within y only change when x is changed, if y is defined as [x]\*2, not when y is defined as x\*2. That is, only when I define y as x nested within a list replicated twice, it responds to changes I make in x.

Is there a reason why it only happens when y is assigned the value of x nested within a list?

martineau
  • 119,623
  • 25
  • 170
  • 301
Hash
  • 147
  • 1
  • 10
  • Can you share the output of the code you posted to make it easier to understand your question? – Samantha Garcia Apr 04 '21 at 13:02
  • `y = x*2` and `y = [x]*2` both create new lists. In the first case, it creates an int list. In the second case it creates and list of references to `x`. It isn't clear why you expect these two things to behave the same way. – John Coleman Apr 04 '21 at 13:03
  • I’m the first case, you’re multiplying the value of x by 2 but it is not setting it to the array. In the second case you’re setting it equal to the array*2, so when you update the array it is connected to the array itself, not just the current value of the array. – Samantha Garcia Apr 04 '21 at 13:06
  • @SamanthaCruz My apologies. I have now edited them into the post in the comments of the code – Hash Apr 04 '21 at 13:09
  • @JohnColeman Why does y = x*2 not create a list of references to x, like y = [x]*2 does, if both of these contain x? – Hash Apr 04 '21 at 13:14
  • @SamanthaCruz Sorry I am a bit confused. What does 'not setting it to the array' mean? Is the array in this case x? – Hash Apr 04 '21 at 13:16
  • Basically in the first case your multiplying the current value of x by 2. In the second case, you’re multiplying x itself by 2 so when x changes, so does y – Samantha Garcia Apr 04 '21 at 13:21
  • `x` contains `1,1,1,1` so of course `x*2` contains `1,1,1,1,1,1,1,1`. `[x]` contains `x`, so `[x]*2` contains `x,x` – John Coleman Apr 04 '21 at 14:15
  • But if [x] contains x, wouldnt that just mean it contains [1,1,1,1]? How is it different from x containing 1,1,1,1 by itself then? – Hash Apr 04 '21 at 18:16

1 Answers1

1

x*2 creates a new list from the values of x

[x]*2 creates a list, that contains x twice => [x, x].

Since x*2 creates a new list, modifying the original won't change the result. In the second case it will.

  • I am confused. Doesn't [x]*2 also have the values of x , since it contains x twice just like x*2? – Hash Apr 04 '21 at 13:11
  • 1
    When you don’t treat x as an array when you multiply, it only uses the current value not the future value. – Samantha Garcia Apr 04 '21 at 13:24
  • 1
    @SamanthaCruz Is there a specific reason why that occurs or is it just how the syntax works? – Hash Apr 04 '21 at 13:34
  • 1
    For most variables, it you assign another variable the same value it creates a copy. For lists, it is different, instead it just creates a second instance of the same list, and a change in the first list would change the other list also. When you did x*2 it didn’t treat x like a list. If you had some y=x, it would have because you’re not performing an operation on the list. For y=[x]*2, you’re creating two lists containing x and not performing operations on x so it’s creating 2 instances of x, not a copies of it. – Samantha Garcia Apr 04 '21 at 13:41
  • You could maybe edit the answer, because I find that this is useful information @SamanthaCruz – Ondřej Baštař Apr 04 '21 at 13:41
  • It won’t let me make that many changes since it’s not my answer but I can post a second answer – Samantha Garcia Apr 04 '21 at 13:47
  • You probably should. I have trouble explaining this concept :) – Ondřej Baštař Apr 04 '21 at 13:49
  • @SamanthaCruz So for non-list values, assigning a variable the same value as contained by another variable creates a copy but if i assign a variable the same list as contained by another list, Python rather than creating a copy, creates a direct reference to the first variable containing a list? And is there a specific reason why its not treated as a list if operators are used? – Hash Apr 04 '21 at 18:19
  • Yes. See here: https://developers.google.com/edu/python/lists – Samantha Garcia Apr 04 '21 at 18:24
  • I’m not sure why it doesn’t do that when an operator is used, but I would guess to create consistency with operations – Samantha Garcia Apr 04 '21 at 18:26