0

I get strange results when using the setdefault method:

def initialize_dict(patients, default):
    d = {}
    for patient in patients:
        d.setdefault(patient, default)
    return d

keys = ["A", "B"]
values = initialize_dict(keys, [])
values["A"].append(1)
values
{'A': [1], 'B': [1]}

Why does it append 1 to "A" and "B"? Thanks!

b4shy
  • 13
  • 1

1 Answers1

1

Look at:

values = initialize_dict(keys, [])

What happens here:

  • initialize_dict is called with two lists: one for keys and one for the default value

Looking into:

def initialize_dict(patients, default):
    d = {}
    for patient in patients:
        d.setdefault(patient, default)
    return d

What you do is take the default value and assign it to the keys. Note however, that there was always only one list created! In other words, the same list is assigned as the value of d["A"] and d["B"] - or maybe better, they both point to the same object in memory. As a result, modifying d["A"] changes the value of d["B"]

To avoid this, one solution would be to copy the default value

from copy import copy

def initialize_dict(patients, default):
    d = {}
    for patient in patients:
        d.setdefault(patient, copy(default)) # << HERE!
    return d

Note that by default, copy.copy does a shallow copy. Depending on what you are trying to do you might need to use copy.deepcopy

Finally, as others have said, this is a good fit/use-case for defaultdict

urban
  • 5,392
  • 3
  • 19
  • 45