-1

Note: This was part of a much larger, more complex piece of code where this single line of code made sense given the context. I know I can simply write 1 in the list.

The code I am referring to is from another question here: How to implement an efficient bidirectional hash table?

Anyway, what I don't understand is why the return value, a list, can be appended to, and why that change in reflected within the list contained inside the dictionary. As far as I knew, the returned value was a somewhat copy of the list, not the same list itself in the dictionary:

>>> dict = {}
>>> dict.setdefault("a",[]).append(1)
>>> print(dict)
>>> {"a": [1]}

At first, I thought this was because the list returned is only returned after the execution of the line, which seemed to make a lot of sense, so to test this I assigned the result of dict.setdefault("a", []) to a variable:

>>> dict = {}
>>> l = dict.setdefault("a",[])
>>> l.append(1)
>>> print(l)
>>> [1]
>>> print(dict)
>>> {"a": [1]}

What's even stranger, is that appending to the list directly does not work. By directly, I mean this:

>>> dict = {}
>>> dict.setdefault("a",[].append(1))
>>> print(dict)
>>> {"a": None}    

So what I would not have expected to be possible is what actually happened (changing a returned value with that change being made to the copy of that value), and what I thought would be possible is not (appending directly to a list).

If anyone knows why this is, and wherein the python documentation I may be able to read up more about this behaviour to further my understanding, that would be greatly appreciated.

Thanks.

Jim Jam
  • 631
  • 2
  • 9
  • 19

1 Answers1

0

dict.setdefault(key, value) returns the value corresponding to key, creating the key and value in the dict if necessary. So in the example, a list is created and returned, and then the list is appended to.

>>> d = {}
>>> d.setdefault('a', [])
[]

>>> d = {}
>>> d.setdefault('a', []).append(1)
>>> d
{'a': [1]}

From the docs:

setdefault(key[, default])

If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.

snakecharmerb
  • 36,887
  • 10
  • 71
  • 115
  • Thank you, but I already understood that. What I don't understand is why the list in the dictionary can be modified when returned, like so: dict.setdefault("a",[]).append(1), and also why the list in said dictionary cannot be appended to directly like so: [].append(1) – Jim Jam Oct 27 '19 at 19:37
  • @user2901512: because it's the same list, not a copy (Python almost never makes copies). The problem with `[].append(1)` is that append only mutates the list and doesn't return it; so that creates a list, then appends 1 to it, then discards the list and returns None (append's return value). – RemcoGerlich Oct 27 '19 at 20:01