Как выполнить итерацию по словарю Python, установив ключ словаря в качестве значения другого словаря

#python #list #dictionary #immutability

#python #Список #словарь #неизменяемость

Вопрос:

Я работаю на C , я новичок в Python, и я подозреваю, что эта проблема как-то связана с изменчивостью [im].

Я создаю представление JSON в Python, которое включает в себя несколько слоев вложенных списков и словарей в одном «объекте». Моя цель — вызвать jsonify конечный результат и сделать его похожим на хорошо структурированные данные.

Я столкнулся с проблемой при создании объекта:

 approval_groups_list = list()
approval_group_dict = dict()

for groupMemKey, groupvals in groupsAndMembersDict.items():
    approval_group_dict["group_name"] = groupMemKey  
    approval_group_dict["name_dot_numbers"] = groupvals # groupvals is a list of strings
    approval_groups_list.append(approval_group_dict)

entity_approval_unit["approval_groups"] = approval_groups_list
  

Первый запуск выполняется так, как ожидалось, но после того, какой бы groupMemkey ни был затронут последним, это то, что отражают все остальные объекты.

 groupsAndMembersDict= {
 'Art': ['string.1', 'string.2', 'string.3'],
 'Math': ['string.10', 'string.20', 'string.30']
}
  

Ожидаемый результат:

approval_groups:

 [
 {
  "group_name": "Art",
  "name_dot_numbers": ['string.1', 'string.2', 'string.3']
 },
 {
  "group_name": "Math",
  "name_dot_numbers": ['string.10', 'string.20', 'string.30']
 }
]
  

Фактический результат:

approval_groups:

 [
 {
  "group_name": "Math",
  "name_dot_numbers": ['string.10', 'string.20', 'string.30']
 },
 {
  "group_name": "Math",
  "name_dot_numbers": ['string.10', 'string.20', 'string.30']
 }
]
  

Что происходит, и как мне это исправить?

Комментарии:

1.Потому что вы продолжаете назначать один и тот же список одному и тому же dict approval_group_dict["name_dot_numbers"] = groupvals и впоследствии добавляете его к approval_groups_list . Это не имеет ничего общего с изменчивостью / неизменяемостью. Проще говоря, approval_group_dict["name_dot_numbers"] = groupvals не создает копию groupvals и approval_groups_list.append(approval_group_dict) не создает копию approval_group_dict

Ответ №1:

Ваша проблема заключается не в неизменности, а в изменчивости объектов. Я уверен, что вы получили бы тот же результат с эквивалентным кодом C .

Вы создаете approval_group_dict перед for циклом и продолжаете использовать его повторно. Все, что вам нужно сделать, это переместить конструкцию внутрь for , чтобы для каждого цикла создавался новый объект:

 approval_groups_list = list()

for groupMemKey, groupvals in groupsAndMembersDict.items():
    approval_group_dict = dict()
    ...
  

Ответ №2:

При написании этого вопроса мне пришло в голову попробовать несколько вещей, включая это, которые устранили мою проблему — однако я до сих пор точно не знаю, почему это работает. Возможно, это больше похоже на проблему с указателем / ссылкой?

 approval_groups_list = list()
approval_group_dict = dict()

for groupMemKey, groupvals in groupsAndMembersDict.items():
    approval_group_dict["group_name"] = groupMemKey  
    approval_group_dict["name_dot_numbers"] = groupvals 
    approval_groups_list.append(approval_group_dict.copy())  # <== note, here is the difference ".copy()"

entity_approval_unit["approval_groups"] = approval_groups_list
  

РЕДАКТИРОВАТЬ: Проблема заключается в том, что Python все время передается по ссылке [object]. Если вы новичок в Python, как и я, это означает: «передавайте по ссылке, за исключением случаев, когда передаваемая вами вещь неизменяема, тогда она передается по значению». Таким образом, в некотором смысле это действительно имело отношение к изменчивости [im]. В основном это было связано с моим непониманием того, как Python передает ссылки.

Комментарии:

1. В принципе, все в Python действует как ссылка, ничто никогда не копируется неявно.

2. да, это было оно.