1

Suppose we have a list a=[1,2,3] and I need to copy elements of a to new list b.

we can do a=b but both a and b point to the same list. Hence mutating either of them mutates both the lists.

>>> a=b
>>> a
[1, 2, 3]
>>> b
[1, 2, 3]
>>> b.append(4)
>>> a,b
([1, 2, 3, 4], [1, 2, 3, 4])
>>> a.append(5)
>>> a,b
([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
>>> a is b
True
>>> id(a),id(b)
(2287659980360, 2287659980360)

To avoid this we can do b=a[:]. a[:] creates a different list with the same values of a. Now, even if I mutate a, b will not be affected and vice-versa. b and b[:] are two different lists.

>>> b=a[:]
>>> a,b
([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
>>> a.append(6)
>>> a,b
([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5])
>>> b.append(6)
>>> a,b
([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6])
>>> a is b
False
>>> id(a),id(b)
(2287659980360, 2287653308552)

Now, if I do b[:]=a my list b is being mutated. But b[:] is another list right? Both b and b[:] point to different lists right? Correct me if I'm wrong. Why is b being changed if I mutate b[:]. What am I missing?

>>> a=['a','b','c']
>>> b[:]=a
>>> a,b
(['a', 'b', 'c'], ['a', 'b', 'c'])
>>> id(b),id(b[:])
(2287653308552, 2287660267080)
>>> b is b[:]
False
Vega
  • 27,856
  • 27
  • 95
  • 103
Ch3steR
  • 20,090
  • 4
  • 28
  • 58
  • `"Now, if I do b[:]=a my list b is being mutated."` not exactly mutated, rather overwritten by another list, which is renamed as `b`. – Sayandip Dutta Jan 15 '20 at 09:41
  • Not an expert, but I assume that when `b[:]` is assigned to, it modifies the list `b`. However, when `b[:]` is called on the right hand side, it returns a list containing every element of `b`, which points to a different location# – clubby789 Jan 15 '20 at 09:47
  • @SayandipDutta absolutely not. The list being referred to by `b` is being mutated. – juanpa.arrivillaga Jan 15 '20 at 09:54
  • 2
    You are confusing two things, slicing and slice-based assignment. The expression `x[:]` creates a slice, implicitly calling `x.__getitem__`, whereas the statement `x[:] = b` is slice assignment, which calls `x.__setitem__` – juanpa.arrivillaga Jan 15 '20 at 09:56
  • @juanpa.arrivillaga Thanks for taking out your time in explaining and finding a similar question.Now I understood the difference. – Ch3steR Jan 15 '20 at 09:59
  • Please keep Q&A style posts as they are, do not post answers in the question post – Vega Feb 15 '20 at 04:35

1 Answers1

7

Slicing means different things when used as an expression or as an assignment target.

As an expression, evaluating b[:] produces a new list. However, as an assignment target, assigning to b[:] does not mean "evaluate the expression b[:] and then assign to the resulting list". You can't assign to objects in Python, anyway.

As an assignment target, assigning to b[:] tells the existing list to replace its contents with the elements of whatever you're assigning to b[:]. This is handled by the __setitem__ method, like b.__setitem__(slice(None, None), a). No new list is produced, and b[:] is not evaluated as an expression.

You can see this described in the language reference documentation for assignment statements, under "If the target is a slicing" (although some of the constraints for slice assignment aren't as strict as what the documentation describes; for example, the docs say the sequence types need to match, but for most types, they don't).

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Thanks this is what I was looking for. Pretty clear explanation. – Ch3steR Jan 15 '20 at 09:53
  • What did you mean by `You can't assign to objects in Python, anyway` – Willwsharp Feb 14 '20 at 17:51
  • @Willwsharp: Assignment assigns to things like variables or attributes in Python, not objects. This is in contrast to languages like C++. – user2357112 Feb 14 '20 at 17:54
  • @user2357112supportsMonica Hmm what does that look like in C++? I think I'm drawing a blank on this. Thanks! – Willwsharp Feb 14 '20 at 17:55
  • @Willwsharp: In Python, if you do `a.b = c`, then `a` is responsible for rebinding its `b` attribute. In C++, if you do `a.b = c;`, then the `a.b` object is responsible for modifying itself to look like `c`. – user2357112 Feb 14 '20 at 18:06
  • @user2357112supportsMonica Oh I think I understand. What should I search to learn more about this? – Willwsharp Feb 14 '20 at 19:44