Ad

How To Properly Use Dic.setdefault(key,[]).append()

- 1 answer

a=[{'kart': ['alice', 'marie'],
  'vinod': ['alice', 'marie'],
  'jordan': ['alice', 'marie'],
  'joe': ['marie', 'alice']},
 {'kart': ['alice', 'marie'],
  'vinod': ['alice', 'marie'],
  'jordan': ['alice', 'marie'],
  'joe': ['marie', 'alice']},
 {'kart': ['alice', 'marie'],
  'vinod': ['alice', 'marie'],
  'jordan': ['alice', 'marie'],
  'joe': ['marie', 'alice']}]

I have the above list of dictionaries a. I want the desired output which is below by appending a string to a key of a[0] or the first element in the list.

Desired output:

{'kart': ['marie', 'alice', 'elsie'],
 'vinod': ['alice', 'marie'],
 'jordan': ['marie', 'alice'],
 'joe': ['marie', 'alice']}

Output I am getting:

{'kart': ['alice', 'marie', 'elsie'],
 'vinod': ['alice', 'marie', 'elsie'],
 'jordan': ['alice', 'marie', 'elsie'],
 'joe': ['alice', 'marie', 'elsie']}  

Code I am using:

 import copy
 dic_copy=copy.deepcopy(a[0])
 dic_copy.setdefault("kart",[]).append("elsie")

For some reason the above code is appending to all the keys in the dictionary when I only want it for one key. Any suggestions will help!

Ad

Answer

You problem is that somehow you're creating dictionary with keys that pointing to same list, not four equal lists. This means that once you've changes single value, all others seems to be changed too (in reality, its just single object).

Your setdefault is totally fine, it's "set or get && return".

Your case:

>>> 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']}

Changing dict creation to {k: names[:] for k in ...} will do what you expect – names will be equal, but different objects.

To check this, try identity check with is, i.e.:

>>> d['kart'] is d['joe']  # will be True in your case

Tricky thing is that deepcopy does not change the structure. So if you have dict with keys pointing to same list, deep copy of this dict will have the same structure.

If you have you dict in this structure already and you want to have different identities in values, you can re-create it like:

>>> 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
Ad
source: stackoverflow.com
Ad