【问题标题】:Why does the order matter in this chained assignment?为什么顺序在这个链式分配中很重要?
【发布时间】:2021-08-21 01:43:28
【问题描述】:

如以下两个代码sn-ps所示,链式赋值的顺序很重要(即node = node[ch] = {}不等于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': {}}}}}

为什么顺序很重要?


根据another SO question,链式赋值

a = b = c

相当于:

tmp = c
a = c
b = c

我验证了等效形式产生了相同的行为。即

        # node = node[ch] = {} # chained assignment #1
        tmp = {}
        node = tmp
        node[ch] = tmp

导致print(trie){}

同时

        node[ch] = node = {} # chained assignment #2
        tmp = {}
        node[ch] = tmp
        node = tmp

导致print(trie){'w': {'o': {'r': {'d': {}}}}}

【问题讨论】:

  • 从您的“为什么”问题中备份,您想要的行为是什么?
  • 特别是,您希望nodenode[ch] 指向同一个dict 实例,还是希望它们各自有一个单独的dict?当您拥有a = b = {} 时,只会创建一个新字典。
  • 我怀疑使用 defaultdict 在您的用例中可能很有意义,因为您的目标是能够简洁地定义嵌套字典。
  • def dict_of_dicts(): return collections.defaultdict(dict_of_dicts) 表示如果您指定trie = dict_of_dicts(),那么您可以运行trie['a']['b']['c'] = {},而无需事先初始化trie['a']trie['a']['b']
  • @CharlesDuffy 谢谢!我想要第二个链式分配的行为。 (抱歉回复晚了。)

标签: python chained-assignment


【解决方案1】:

你基本上在最后回答了你的问题。

node = tmp
node[ch] = tmp

node[ch] = tmp
node = tmp

不等价。一旦你执行node = tmp,你就会丢失node 以前的内容,并用新的字典替换它们。这意味着在第一种情况下,您会立即丢失循环内对trie 的引用,并且不能再对其进行变异。在第二种情况下,您更改旧结果,然后将node 重新分配给新字典。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    相关资源
    最近更新 更多