As shown by the following two code snippets, the order of the chained assignment matters (i.e. node = node[ch] = {}
is not equivalent to node[ch] = node = {}
.
trie = {}
node = trie
for ch in "word":
if ch in node:
node = node[ch]
else:
node = node[ch] = {} # chained assignment #1
print(trie) # {}
trie = {}
node = trie
for ch in "word":
if ch in node:
node = node[ch]
else:
node[ch] = node = {} # chained assignment #2
print(trie) # {'w': {'o': {'r': {'d': {}}}}}
Why does the order matter?
According to another SO question, the chained assignment
a = b = c
is equivalent to:
tmp = c
a = c
b = c
and I verified that the equivalent forms produced the same behavior. I.e.
# node = node[ch] = {} # chained assignment #1
tmp = {}
node = tmp
node[ch] = tmp
leads to a print(trie)
of {}
.
Meanwhile
node[ch] = node = {} # chained assignment #2
tmp = {}
node[ch] = tmp
node = tmp
leads to a print(trie)
of {'w': {'o': {'r': {'d': {}}}}}
.
You basically answered your question at the end.
node = tmp
node[ch] = tmp
and
node[ch] = tmp
node = tmp
are not equivalent. As soon as you do node = tmp
, you lose the previous contents of node
, and replace them with a new dict. That means that in the first case, you immediately lose the reference to trie
inside the loop, and can no longer mutate it. In the second case, you alter the old results, then reassign node
to the new dictionary.