0

In the Python documentation it is explained that s * n or n * s means items in the sequence s are not copied; they are referenced multiple times. I am able to get that theoretically but unable to understand the example they have given:

>>> lists = [[]] * 3
>>> lists
[[], [], []] # Output
>>> lists[0].append(3) 
>>> lists
[[3], [3], [3]] # Output

I am confused because if we do the similar thing with strings, it behaves differently as:

list_of_str = (["str"] * 3)
print(list_of_str)
list_of_str[0] = "str_1"
print(list_of_str)
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Shraddha
  • 791
  • 7
  • 13
  • 1
    You're not doing the same thing in the two code snippets. – Some programmer dude Jul 25 '18 at 15:14
  • 3
    You aren't doing a similar thing with strings. They're *immutable*, you're replacing a single item within the outer list. If you did `lists[0] = [3]` you'd see similar behaviour. – jonrsharpe Jul 25 '18 at 15:15
  • 1
    Lists are mutable. Strings are not. `lists[0] = ...` is not the same thing as `lists[0].append(...)`; the latter mutates the object on which you call the method, the former **replaces the reference**. – Martijn Pieters Jul 25 '18 at 15:17
  • You may find this article helpful: [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html), which was written by SO veteran Ned Batchelder. – PM 2Ring Jul 25 '18 at 15:17
  • See https://nedbatchelder.com/text/names.html, and [this visualisation](http://www.pythontutor.com/visualize.html#code=lists%20%3D%20%5B%5B%5D%5D%20*%203%0Alists%5B0%5D.append%283%29%20%0A%0Alist_of_str%20%3D%20%5B%22str%22%5D%20*%203%0Alist_of_str%5B0%5D%20%3D%20%22str_1%22&cumulative=false&curInstr=0&heapPrimitives=true&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false). – Martijn Pieters Jul 25 '18 at 15:19

1 Answers1

1

Your example is not doing the same thing as theirs, because list_of_str[0] = anything would just replace the first entry in the list altogether. It does not matter whether that is a copy or a unique instance.

For a better example, you'd need something like list_of_str[0][0] = 'S' to modify the string itself. But you can't do that, because strings in Python are immutable.

If you want to show conclusively that the entries are referring to the same string, use the id function:

>>> list_of_str = (["str"] * 3)
>>> print(list(map(id, list_of_str)))
[140243211229088, 140243211229088, 140243211229088]
Thomas
  • 174,939
  • 50
  • 355
  • 478
  • This is also explained in the duplicate. I would appreciate if you pinged me when just un-hammering? I've re-closed this post; feel free to ping me in the [Python chat room](https://chat.stackoverflow.com/rooms/info/6/python) if you want to discuss this further. – Martijn Pieters Jul 25 '18 at 15:25
  • @MartijnPieters Sorry, I thought I was merely voting and forgot about my Python superpowers. I don't see this exact question or answer on the duplicate, but never mind. – Thomas Jul 25 '18 at 15:44
  • [List of lists changes reflected across sublists unexpectedly](//stackoverflow.com/a/43246520) covers this situation pretty well. – Martijn Pieters Jul 25 '18 at 15:50
  • Thanks alot Martijin – Shraddha Aug 02 '18 at 15:02