2

In Python

li = [0] * 3
li[0] = 1
# li == [1, 0, 0]

This works fine.

li = [set()] * 3
li[0].add(1)
# li == [{1}, {1}, {1}]

This is adding up 1 for all in the list. What is the difference between this two?

Naveen Pantra
  • 1,236
  • 1
  • 8
  • 7
  • 1
    In the first, you're putting a new object at that position. In the second, you're modifying the object. Since you created only one object and merely put it in the list 3 times, it looks like it modified all three sets, but really it's just one set shown three times. – zondo Aug 22 '18 at 10:35
  • In the first case, you create a list of 10 immutable objects (zeros), each of which is a different object. In the second case, you create a list of 10 mutable set objects, each of which is a reference to the same set. Replacing 0 with 1 swaps in a new, immutable, number object at that position. Modifying the set, affects all sets in the list as they all point at the same, mutable, set object. Also see https://stackoverflow.com/q/30340555/138325 – Trutane Oct 12 '18 at 22:27
  • 1
    Btw @jpp, I don't think this question is a duplicate of 'Python: list of lists'. That's more specifically about list of lists, while the current question is more generally about lists of immutable vs mutable object types. Related yes, but different enough to merit it's own space. – Trutane Oct 12 '18 at 22:48

2 Answers2

3

Here:

li = [0] * 3
li[0] = 1

You create a list with three elements, all of which are the immutable number 0. Then you replace the first element with the immutable number 1.

Whereas here:

li = [set()] * 3
li[0].add(1)

You create a single set (not three sets), and put it into a list three times. You then reference the first element of the list, which of course is the set, and add a number into it. Since only one set was ever created, this appears to modify every element of the list (because they are all the same).

For more about the dangers of [x] * n in Python, see: List of lists changes reflected across sublists unexpectedly

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
0

Objects in Python are stored and used by reference. When you write:

li = [set()] * 3

you are creating an object and then copying its reference; rather than the object itself.

Acorn
  • 24,970
  • 5
  • 40
  • 69