32

I came accross the following code:

# O(n) space       
def rotate(self, nums, k):
    deque = collections.deque(nums)
    k %= len(nums)
    for _ in xrange(k):
        deque.appendleft(deque.pop())
    nums[:] = list(deque) # <- Code in question

What does nums[:] = do that nums = does not? For that matter, what does nums[:] do that nums does not?

Akimiya
  • 184
  • 3
  • 10
sinθ
  • 11,093
  • 25
  • 85
  • 121
  • Asked and answered I believe. [What does \[:\] in Python mean](http://stackoverflow.com/questions/6167238/what-does-in-python-mean) – CollinD Sep 08 '15 at 02:38
  • 1
    @CollinD Didn't see that question, thanks. But still doesn't answer the assignment question – sinθ Sep 08 '15 at 02:39
  • I had voted to reopen because I didn't think the linked duplicate explained slice assignment. I must have opened the wrong link, because it definitely does explain slice assignment. – Josh Smeaton Sep 08 '15 at 03:30

2 Answers2

69

This syntax is a slice assignment. A slice of [:] means the entire list. The difference between nums[:] = and nums = is that the latter doesn't replace elements in the original list. This is observable when there are two references to the list

>>> original = [1, 2, 3]
>>> other = original
>>> original[:] = [0, 0] # changes the contents of the list that both
                         # original and other refer to 
>>> other # see below, now you can see the change through other
[0, 0]

To see the difference just remove the [:] from the assignment above.

>>> original = [1, 2, 3]
>>> other = original
>>> original = [0, 0] # original now refers to a different list than other
>>> other # other remains the same
[1, 2, 3]

Note: vincent thorpe's comments below are either incorrect or irrelevant to the question. This is not a matter of value vs reference semantics, nor whether you apply the operator to an lvalue or rvalue.

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
  • Simply say, (list[:] = ...) is value type but (list = ...) is reference type – Brady Huang Feb 06 '18 at 10:01
  • 2
    @Brady Huang that doesn't describe this accurately – Ryan Haining Feb 06 '18 at 17:11
  • 1
    you are saying that slice notation `list[:]` means the reference, while the `list` means the copy? then why in `for in list:` if you pass the `list` itself and you insert some element inside the loop, this loop will never end because since its incrementing its length it will be forever. it means if yo'u pass `list` without[:] you are passing the reference. that's contradictory huh – vincent thorpe Jul 18 '19 at 08:29
  • 1
    the [:] operator if you put Lvalue or Rvalue it means different – vincent thorpe Jul 18 '19 at 10:33
  • 4
    @vincentthorpe `lst[:]` not followed by an `=` calls `__getitem__`, while `lst[:] = ` calls `__setitem__`, so `[]` and `[]=` are best thought of as two different operators – Ryan Haining Jul 18 '19 at 16:50
  • @Ryan Haining yes l spend serveral hours to find out this. – vincent thorpe Jul 18 '19 at 23:47
14

nums = foo rebinds the name nums to refer to the same object that foo refers to.

nums[:] = foo invokes slice assignment on the object that nums refers to, thus making the contents of the original object a copy of the contents of foo.

Try this:

>>> a = [1,2]
>>> b = [3,4,5]
>>> c = a
>>> c = b
>>> print(a)
[1, 2]
>>> c = a
>>> c[:] = b
>>> print(a)
[3, 4, 5]