Как работает метод setdefault() в этой реализации обратного словаря?
Может ли кто-нибудь объяснить, как происходит назначение словаря "обратный" в случае ниже?
def invert_dict(d):
inverse = {}
for key in d:
new_key = d[key]
inverse.setdefault(new_key, []).append(key)
return inverse
letters_in_word = {"mine": 4, "yours": 5, "ours": 4, "sunday": 6, "friend": 6, "fun": 3, "happy": 5, "beautiful": 8}
print (invert_dict(letters_in_word))
Вывод, конечно, правильный:
{8: ['Beautiful'], 3: ['Fun'], 4: ['My', 'Ours'], 5: ['Happy', 'Yours'], 6: ['Sunday', 'Friend "]}
Документация Python 3.x гласит:
setdefault (ключ [, по умолчанию]):
Если ключ находится в словаре, вернуть его значение. Если нет, вставьте ключ со значением по умолчанию и верните значение по умолчанию. по умолчанию по умолчанию нет.
Позвольте мне использовать пример, чтобы проиллюстрировать, что я делаю и чего не понимаю:
- Предположим, new_key = "счастливый"
- new_key имеет значение 5
- Вызывается setdefault(), и давайте предположим, что 5 уже есть в словаре из "твоего" (насколько я знаю, поскольку словари неупорядочены, это не обязательно так, но давайте предположим) и вернет ["твой" ] (Я предполагаю, что здесь происходит что-то немного другое, так что на самом деле это не так, что "inverse.setdefault(5, [])" возвратил ["ваш"], и это так)
- append () вызывается и ["yours"] -> ["yours", "happy"] - и это то, что у нас осталось.
Я знаю, что к концу 4 я ошибаюсь, потому что на самом деле наш список был присвоен ключу "5". Чего я не понимаю, так это того момента, когда это произошло - похоже, что мы только что вернулись, и нам действительно нужно назначить:
inverse[new_key] = inverse.setdefault(new_key, []).append(key)
Однако, если я запускаю такой код, я получаю ошибку - 'NoneType' object has no attribute 'append'
,
Любое объяснение приветствуется - я полагаю, что мне чего-то не хватает в том, как эти два метода взаимодействуют.
PS Это мой первый вопрос, поэтому прошу прощения, если природа / структура вопроса не "как здесь все делается". Дайте мне знать, как улучшить, и я сделаю все возможное, чтобы сделать это!
1 ответ
Печатные операторы - очень полезный и простой способ понять, что происходит в программе:
def invert_dict(d):
inverse = {}
for key in d:
new_key = d[key]
print('key:', key)
print('new_key:', new_key)
print('inverse before:', inverse)
value = inverse.setdefault(new_key, [])
print('inverse in the middle:', inverse)
print('value before:', value)
value.append(key)
print('value after:', value)
print('inverse after:', inverse)
return inverse
letters_in_word = {"mine": 4, "yours": 5, "ours": 4, "sunday": 6, "friend": 6, "fun": 3, "happy": 5, "beautiful": 8}
print(invert_dict(letters_in_word))
Выход:
key: beautiful
new_key: 8
inverse before: {}
inverse in the middle: {8: []}
value before: []
value after: ['beautiful']
inverse after: {8: ['beautiful']}
key: yours
new_key: 5
inverse before: {8: ['beautiful']}
inverse in the middle: {8: ['beautiful'], 5: []}
value before: []
value after: ['yours']
inverse after: {8: ['beautiful'], 5: ['yours']}
key: ours
new_key: 4
inverse before: {8: ['beautiful'], 5: ['yours']}
inverse in the middle: {8: ['beautiful'], 4: [], 5: ['yours']}
value before: []
value after: ['ours']
inverse after: {8: ['beautiful'], 4: ['ours'], 5: ['yours']}
key: sunday
new_key: 6
inverse before: {8: ['beautiful'], 4: ['ours'], 5: ['yours']}
inverse in the middle: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: []}
value before: []
value after: ['sunday']
inverse after: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: ['sunday']}
key: happy
new_key: 5
inverse before: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: ['sunday']}
inverse in the middle: {8: ['beautiful'], 4: ['ours'], 5: ['yours'], 6: ['sunday']}
value before: ['yours']
value after: ['yours', 'happy']
inverse after: {8: ['beautiful'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
key: fun
new_key: 3
inverse before: {8: ['beautiful'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
inverse in the middle: {8: ['beautiful'], 3: [], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
value before: []
value after: ['fun']
inverse after: {8: ['beautiful'], 3: ['fun'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
key: mine
new_key: 4
inverse before: {8: ['beautiful'], 3: ['fun'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
inverse in the middle: {8: ['beautiful'], 3: ['fun'], 4: ['ours'], 5: ['yours', 'happy'], 6: ['sunday']}
value before: ['ours']
value after: ['ours', 'mine']
inverse after: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday']}
key: friend
new_key: 6
inverse before: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday']}
inverse in the middle: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday']}
value before: ['sunday']
value after: ['sunday', 'friend']
inverse after: {8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday', 'friend']}
{8: ['beautiful'], 3: ['fun'], 4: ['ours', 'mine'], 5: ['yours', 'happy'], 6: ['sunday', 'friend']}
Также очень полезен хороший отладчик, такой как в PyCharm. Попробуйте это.