0

Inspired from this riddle in "Fluent Python":

t = (1, 2, [3,4])
t[2] += [5, 6]

For those who don't know, it will raise an error, but will change the tuple.

I don't understand 2 things:

  1. Why t[2].extend([5, 6]) will work, without any errors?

  2. Why an insert of new entry to dictionary will work without any error:

    t = (1, {}) t[1]["name"] = "bob"

Emanuel
  • 640
  • 1
  • 7
  • 25
  • [If in Python I put a list inside a tuple, can I safely change the contents of that list?](https://stackoverflow.com/q/26262813/2301450) – vaultah Aug 21 '17 at 21:53
  • 1. Because that's not trying to assign to `t[2]`. 2. Because dictionaries are also mutable, and again you're not trying to assign to a tuple element. – jonrsharpe Aug 21 '17 at 21:54

1 Answers1

1

This is because with extend and the dict you're mutating the objects themselves after retrieving them, rather than trying to assign to the tuple.

t[2] += [5, 6]

is actually kind of equivalent to

t[2] = t[2] + [5, 6]

which is clearly not allowed. (This calls __setitem__ under the hood)

However, t[2].extend([5, 6]) only gets the item (using __getitem__, which is permitted), and once it has the object is uses extend. The object is still the same object though - you may think of it as the pointer not having changed.

The case in your comment is an interesting one - again, it gets the object in the first statement b = t[2] and then already having the object mutates the object itself. You can see that this won't result in any call to the tuple's __setitem__. Refer to the dupe link for info on why it's possible to mutate tuple elements.

Izaak van Dongen
  • 2,450
  • 13
  • 23