为什么a = a ['k'] = {}创建无限嵌套的字典?

时间:2019-02-21 13:37:34

标签: python dictionary reference assignment-operator operator-precedence

这是我的Python代码,它创建了一个无限嵌套的字典:

a = a['k'] = {}

print(a)
print(a['k'])
print(a['k']['k'])
print(a is a['k'])

以下是输出:

{'k': {...}}
{'k': {...}}
{'k': {...}}
True

输出显示a['k']引用a本身,从而使其无限嵌套。

我猜这句话:

a = a['k'] = {}

表现如下:

new = {}
a = new
a['k'] = new

这确实会创建一个无限嵌套的字典。

我查看了 Python语言参考Section 7.2: Assignment statements,但找不到任何暗示a = a['k'] = {}应该首先将a设置为新字典的内容然后在该字典中插入一个键/值对。以下是我发现相关但未回答我问题的参考摘录:

  

如果目标列表是没有尾随逗号的单个目标,则可以选择将其分配给该目标。

  

如果目标是预订:评估引用中的主表达式。它应该产生可变的序列对象(例如列表)或映射对象(例如字典)。接下来,计算下标表达式。

  

如果主要对象是映射对象(例如字典),则下标必须具有与该映射的键类型兼容的类型,然后要求该映射创建一个键/基准对,该键/数据对将下标映射到所分配的宾语。可以用相同的键值替换现有的键/值对,也可以插入新的键/值对(如果不存在具有相同值的键)。

这些摘录中的每一个都定义了具有单个目标(例如a = {}a['k'] = {})的作业的行为,但是它们似乎并没有讨论在a = a['k'] = {}的情况下应该发生的情况。 。这种陈述的评估顺序在哪里记录?

1 个答案:

答案 0 :(得分:4)

根据the section 7.2 you quoted(强调我的观点),从左到右解决分配声明中的分配:

  

赋值语句评估表达式列表(请记住,   这可以是单个表达式或逗号分隔的列表,后者   产生一个元组),并将单个结果对象分配给每个对象   目标列表,从左到右

这意味着,确实,您的陈述等同于:

new = {}
a = new
a['k'] = new

作为快速的反证明,交换分配顺序会导致错误:

a['k'] = a = {}

提高

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined