Scott
Scott

Reputation: 15

Function to create dictionary with default values that can be either immutable or mutable

I have a function to create a dictionary with specific keys, which accepts a parameter to specify what each key's "default" value should be.

def new_dict(entrys_default=0):
    my_dict = {}
    for k in ['a', 'b', 'c']:
        my_dict[k] = entrys_default
    return my_dict

The issue is that when I call it with new_dict(entrys_default=[]) so that each entry in the dictionary is created with a new empty list as its value, when I then update one entry with returned_dict['a'].append(123) then all entries are updated:

{'a': [123], 'b': [123], 'c': [123]}

This doesn't happen when using an integer, and I understand that it is because the entrys_default is immutable when it is an integer, but is a reference to the same list when it is a list or dictionary.

I want to be able to have this function work the same as it does for integer parameters with lists and dictionaries as entrys_default - i.e. each entry has its own list/dictionary - but want to keep the function flexible to also work for integers.

Can anyone please suggest the best way to go about this?

Upvotes: 0

Views: 104

Answers (1)

chepner
chepner

Reputation: 531215

Do what collections.defaultdict does; instead of taking an "example" default value, take a function that returns the desired default value. Then call that function and use its return value to initialize each element of the dict being constructed.

def new_dict(make_default=int):  # int() == 0
    my_dict = {}
    for k in ['a', 'b', 'c']:
        my_dict[k] = make_default()
    return my_dict

d = new_dict(list)  # list() == [], but a distinct list each time it is called
d['a'].append(123)
assert d['a'] != d['b']

Upvotes: 2

Related Questions