Reputation: 18727
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
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
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
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
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