10

I normally understand how slices behave to the left and right of the assignment operator.

However, I've seen this in the Python (3.8.0) manual and trying to figure out what I'm missing.

clear the list by replacing all the elements with an empty list

letters[:] = []

How's that different from just letters = []?

(It's not easy to search for [:] as stackoverflow thinks you're looking for a tag. So, if there is already an answer I couldn't locate it.)

I see some rather irrelevant answers. So, to hopefully clarity, the question is not about what the [:] slice means, rather about assigning the empty list to one.

tonypdmtr
  • 3,037
  • 2
  • 17
  • 29
  • https://stackoverflow.com/questions/39241529/what-is-the-meaning-of-in-python – qristjan Nov 06 '19 at 11:55
  • 2
    So, I guess it's only a matter of internal memory usage (reusing the same memory rather than creating a new list). No difference in perceivable code behavior, correct? – tonypdmtr Nov 06 '19 at 11:57
  • 1
    @tonypdmtr: there is a definite difference if some other variable also points to the list that `letters` points to. If you just use `letters =` then the other variable won't be affected, but if you use `letters[:] =` then the value visible via the other variable is modified! – Joachim Sauer Nov 06 '19 at 12:05
  • @JoachimSauer OK, thanks, that's indeed significant to remember. – tonypdmtr Nov 06 '19 at 12:09
  • 1
    One place where this difference is most often seen is when `letters` is a function parameter. Then `letters[:] = []` will change the argument passed to the function but `letters = []` won't. – interjay Nov 06 '19 at 12:21
  • @interjay That's also good to know. I think I got it now. Thank you all for your great answers. Sorry I could accept only one! – tonypdmtr Nov 06 '19 at 12:23

3 Answers3

9

The assignment var = [] binds the name var to the newly created list. The name var may or may not have been previously bound to any other list, and if it has, that list will remain unchanged.

On the other hand, var[:] = [] expects var to be already bound to a list, and that list is changed in-place.

That's why the behaviour in these two cases is different:

var1 = [1, 2, 3]
var2 = var1
var1 = []
print(var1, var2)  # prints [] [1, 2, 3]

var1 = [1, 2, 3]
var2 = var1
var1[:] = []
print(var1, var2)  # prints [] []
bereal
  • 32,519
  • 6
  • 58
  • 104
7

This code demonstrates what is going on:

original = ['a','b','c']

letters = original

print('Same List')
print(original)
print(letters)

letters = []

print('Different lists')
print(original)
print(letters)

letters = original

letters[:] = []

print('Same list, but empty')
print(original)
print(letters)

Output:

Same List
['a', 'b', 'c']
['a', 'b', 'c']
Different lists
['a', 'b', 'c']
[]
Same list, but empty
[]
[]

The first part of the code: letters = original means that both variables refer to the same list.

The second part: letters = [] shows that the two variables now refer to different lists.

The third part: letters = original; letters[:] = [] starts with both variables referring to the same list again, but then the list itself is modified (using [:]) and both variables still refer to the same, but now modified list.

quamrana
  • 37,849
  • 12
  • 53
  • 71
5

var = [] is an assignment to the name var. It replaces what, if anything, var used to refer to with [].

var[:] = [] is a method call in disguise: var.__setitem__(slice(), []). It replaces the elements referred to by the slice (in this case, all of them) with the elements in [], effectively emptying the list without replacing it altogether.

Incidentally, you can use var.clear() to accomplish the same thing; slice assignment more generally lets you replace one range of values with another, possibly longer or shorter, range of values.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • does it copy the list in a new one or is it in place ? – Sanhaji Omar Nov 27 '19 at 01:17
  • It's in-place. Probably the best way to see this is with something like `var = [1,2,3]; b = var; var[:] = []; assert b == []`. The change made via `var` is visible via `b` as well. – chepner Nov 27 '19 at 01:34