names_to_bands.setdefault(name,[]).append('Wings')

функция в цикле возвращает в цикле список с именем и названием группы Вопрос почему при повторном прогоне она добаляет имя группы к уже существующему имени?

band1_names = ['John', 'George', 'Paul', 'Ringo']
band2_names = ['Paul']
names_to_bands = {}
for name in band1_names:
    names_to_bands.setdefault(name,['Beatles'])
for name in band2_names:
    names_to_bands.setdefault(name,[]).append('Wings')
print(names_to_bands['Paul'])


['Beatles', 'Wings']

P/S/ names_to_bands = {'John': ['Beatles'], 'George': ['Beatles'], 'Paul': ['Beatles', 'Wings'], 'Ringo': ['Beatles']}


Ответы (1 шт):

Автор решения: Roman Konoval

Вы неправильно используете setdefault в комбинации с append. Главное, что вызов этого метода и вызов append независимы.

setdefault возвращает значение из dict по ключу (подобно тому, как это делает get или []), а в случае, если такого ключа нет, добавляет в dict значение для данного ключа, переданное вторым параметром. И самое главное, что append вызывается в любом случае для списка.

Это значит, что эта строка:

names_to_bands.setdefault(name,[]).append('Wings')

работает так:

  1. если name в names_to_bands нет, то она эквивалента names_to_bands[name] = ['Wings']
  2. если name в names_to_bands уже есть, то она эквивалентна names_to_bands[name].append('Wings')

Т.е. при повторном вызове добавится дубликат, что вы и наблюдаете.

То, что вам нужно делается так:

bands = names_to_bands.setdefault(name,[])
if 'Wings' not in bands:
    bands.append('Wings')

либо используйте set вместо списка:

names_to_bands.setdefault(name, set()).add('Wings')
→ Ссылка