Mp0int
Mp0int

Reputation: 18727

Initializing unknown number of keys with specific values in a dictionary in Python

This is a kind of best practices question. Performance is important.

I have a list of strings, number of strings are not a constant number (may change from query to query). I wish to create a dictionary of these strings as keys and assing them a static value (which is constant and will same for all keys in the list). Like:

my_keys = ['AKey', 'AnotherKey', 'OneMore']

default_Value = dict({'count':0, 'basePrice': 0})

Expected Output:

{'AKey': {'count':0, 'basePrice': 0}, 'AnotherKey': {'count':0, 'basePrice': 0}, 'OneMore': {'count':0, 'basePrice': 0}}

Each value dictionary ({'count':0, 'basePrice': 0}) must be a separate object, not references of a single dictionary object.

I am looking for something except for loops.

I tried the following and it works when the number of keys are known.

dict(zip(my_keys, [dict(), dict(), dict()]))

But since the number of items in my_keys will change, this approaches fail.

Upvotes: 1

Views: 1406

Answers (5)

jamylak
jamylak

Reputation: 133564

Shallow copies, as suggested by the other answers, may not be good enough:

>>> from copy import deepcopy
>>> my_keys = ['AKey', 'AnotherKey', 'OneMore']
>>> default_Value = dict({'count':0, 'basePrice': 0})
>>> {k: deepcopy(default_Value) for k in my_keys}
{'OneMore': {'count': 0, 'basePrice': 0}, 'AKey': {'count': 0, 'basePrice': 0}, 'AnotherKey': {'count': 0, 'basePrice': 0}}

This is assuming you don't know your default_Value in advance eg. you can just plug in {'count':0, 'basePrice': 0} straight into a dictionary comprehension as shown by @MartijnPieters, which would be better in that case

As suggested by @gnibbler it might be faster to use pickle.loads in the dict comp.

>>> import pickle
>>> default_Value = dict({'count':0, 'basePrice': 0})
>>> _default_Value = pickle.dumps(default_Value)
>>> {k: pickle.loads(_default_Value) for k in my_keys}
{'OneMore': {'count': 0, 'basePrice': 0}, 'AKey': {'count': 0, 'basePrice': 0}, 'AnotherKey': {'count': 0, 'basePrice': 0}}

Upvotes: 2

hsen
hsen

Reputation: 427

dict(itertools.product(my_keys,[default_Value]))

Upvotes: -1

georg
georg

Reputation: 214969

What's wrong with

dct = defaultdict(lambda: {'count':0, 'basePrice': 0})

Explanation: it doesn't make sense to pre-populate the dict with the values which you don't use. And if you do, defaultdict will create them for you on the fly. I don't think anything can beat this performance-wise.

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1122092

You cannot avoid a loop; a dict comprehension is the best practice for creating a dictionary from a sequence of keys with a mutable value:

{key: {'count':0, 'basePrice': 0} for key in my_keys}

For Python 2.6 and earlier, use a generator expression and the dict() constructor:

dict((key, {'count':0, 'basePrice': 0}) for key in my_keys)

For completion's sake, for a default value that is not mutable, dict.fromkeys() is the better and faster alternative.

Upvotes: 5

user4815162342
user4815162342

Reputation: 154986

A dict comprehension is what you would typically use for this:

{key: default_Value.copy() for key in my_keys}

Note that you need to copy default_value to avoid the same dict instance getting reused for all keys.

Upvotes: 2

Related Questions