Ваша проблема в том, что каким-то образом вы создаете словарь с ключами, указывающими на тот же список , а не на четыре равных списка. Это означает, что после того, как вы измените одно значение, все другие, похоже, тоже изменятся (в действительности это просто один объект).
Ваша setdefault полностью в порядке, это "установить или получить && return".
Ваш случай:
>>> names = ['marie', 'alice']
>>> d = {k: names for k in ['kart', 'vinod', 'jordan', 'joe']}
>>> d.setdefault('kart', []).append('elsie')
>>> d
{'kart': ['marie', 'alice', 'elsie'],
'vinod': ['marie', 'alice', 'elsie'],
'jordan': ['marie', 'alice', 'elsie'],
'joe': ['marie', 'alice', 'elsie']}
Изменение создания дикта на {k: names[:] for k in ...}
будет делать то, что вы ожидаете - имена будут одинаковыми, но разные объекты.
Чтобы проверить это, попробуйте проверить личность с помощью is
, т. Е .:
>>> d['kart'] is d['joe'] # will be True in your case
Хитрость в том, что deepcopy
не меняет структуру. Поэтому, если у вас есть диктовка с ключами, указывающими на один и тот же список, глубокая копия этого диктанта будет иметь такую же структуру.
Если у вас уже есть диктант в этой структуре, и вы хотите иметь разные тождества в значениях, вы можете воссоздать его следующим образом:
>>> names = ['marie', 'alice']
>>> d = {k: names for k in ['kart', 'vinod', 'jordan', 'joe']}
>>> d['kart'] is d['joe']
True
>>> d = {k:v[:] for k, v in d.items()}
>>> d['kart'] is d['joe']
False