pythonchained-assignment

Why does the order matter in this chained assignment?


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': {}}}}}.


Solution

  • 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.