Почему a = a ['k'] = {} создает бесконечно вложенный словарь? - PullRequest
0 голосов
/ 21 февраля 2019

Вот мой код 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

, что действительно создает бесконечно вложенный словарь.

Я посмотрел на Раздел 7.2: Операторы присваивания из Справочник по языку Python , но я не смог найти ничего, что подразумевало бы, что a = a['k'] = {} должен сначала установить a в новый словарь и затем вставьте пару ключ / значение в этот словарь.Вот некоторые выдержки из ссылки, которые я нашел уместными, но не ответил на мой вопрос:

Если список целей - это одна цель без запятой, необязательно в скобках, объект назначается этомуtarget.

Если целью является подписка: оценивается основное выражение в ссылке.Он должен давать либо объект изменяемой последовательности (такой как список), либо объект отображения (такой как словарь).Затем выполняется выражение подстрочного индекса.

Если первичным является объект сопоставления (например, словарь), индекс должен иметь тип, совместимый с типом ключа сопоставления и сопоставлениемЗатем предлагается создать пару ключ / элемент данных, которая сопоставляет индекс с назначенным объектом.Это может либо заменить существующую пару ключ / значение тем же значением ключа, либо вставить новую пару ключ / значение (если не было ключа с таким же значением).

Каждый из этих отрывков определяетповедение назначения с единственной целью, такой как a = {} и a['k'] = {}, но они, кажется, не говорят о том, что должно произойти в случае a = a['k'] = {}.Где задокументирован порядок оценки такого заявления?

1 Ответ

0 голосов
/ 21 февраля 2019

Назначения в операторе присваивания разрешаются слева направо , согласно указанному вами разделу 7.2 (выделено мной):

НазначениеОператор оценивает список выражений (помните, что это может быть одно выражение или список, разделенный запятыми, последний дает кортеж) и назначает один результирующий объект каждому из целевых списков, слева направо .

Это означает, что да, действительно, ваше утверждение эквивалентно:

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