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

Why does a = a['k'] = {} create an infinitely nested dictionary?

这是我的 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 到新词典 然后 在该词典中插入一个 key/value 对。以下是我发现相关但未回答我的问题的参考资料的一些摘录:

If the target list is a single target with no trailing comma, optionally in parentheses, the object is assigned to that target.

If the target is a subscription: The primary expression in the reference is evaluated. It should yield either a mutable sequence object (such as a list) or a mapping object (such as a dictionary). Next, the subscript expression is evaluated.

If the primary is a mapping object (such as a dictionary), the subscript must have a type compatible with the mapping’s key type, and the mapping is then asked to create a key/datum pair which maps the subscript to the assigned object. This can either replace an existing key/value pair with the same key value, or insert a new key/value pair (if no key with the same value existed).

这些摘录中的每一个都定义了具有单个目标(例如 a = {}a['k'] = {} 的赋值行为,但它们似乎没有谈论在 [=19 的情况下应该发生什么=].在哪里记录了这种声明的评估顺序?


此问题现已解决。 的回答指向了Section 7.2: Assignment statements的相关条款。相关条款在开头是正确的,但我之前忽略了它。在这里:

An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.

现在让我们将其与语法进行比较。

赋值语句定义为

assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)

所以声明

a = a['k'] = {}

有两个 target_list 元素,即 aa['k'],以及一个 starred_expression 元素,即 {},所以 {} 从左到右分配给每个目标列表 aa['k']

赋值语句中的赋值从左到右,根据the section 7.2 you quoted(强调我的):

An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.

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

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