Everyone who's done Python for a while soon learns that dicts are mutable. I.e. that they can change.
One way of "forking" a dictionary into two different ones is to create a new dictionary object with dict()
. E.g:
>>> first = {'key': 'value'}
>>> second = dict(first)
>>> second['key'] = 'other'
>>> first
{'key': 'value'}
>>> second
{'key': 'other'}
See, you can change the value of a key without affecting the dictionary it came from.
But, if one of the values is also mutable, beware!
>>> first = {'key': ['value']}
>>> second = dict(first)
>>> second['key'].append('second value')
>>> first
{'key': ['value', 'second value']}
>>> second
{'key': ['value', 'second value']}
This is where you need to use the built in copy.deepcopy
.
>>> import copy
>>> first = {'key': ['value']}
>>> second = copy.deepcopy(first)
>>> second['key'].append('second value')
>>> first
{'key': ['value']}
>>> second
{'key': ['value', 'second value']}
Yay! Hope it helps someone avoid some possibly confusing bugs some day.
UPDATE
As ëRiC reminded me, there are actually three ways to make a "shallow copy" of a dictionary:
1) some_copy = dict(some_dict)
2) some_copy = some_dict.copy()
3) some_copy = copy.copy(some_dict) # after importing 'copy'
Comments
Post your own commentwow... thanks for the post :)
Dicts have a copy method right away!
d = {'asdf': ['value']}
dd = d.copy()
dd['asdf'] = ['other']
d
# Result: {'asdf': ['value']} #
dd
# Result: {'asdf': ['other']} #
(can it really be!? I contributed something?!! :D)
Note that using obj.copy() should probably be preferred to dict(obj) since the former approach allows someone to override the copy operation in subclasses whereas the latter does not.
Although by default obj.copy() returns a dict, if someone has chosen to return an instance of the type(obj) then only that approach will have the intended result. (As with any such advice, this applies to the general case but not, by definition, if you have a good reason to do it differently.)
Awesome post thank you
Thank YOU so much!
copy.deepcopy is way slower than dict comprehension -
https://stackoverflow.com/questions/20772885/is-python-deepcopy-more-efficient-than-custom-code-or-less-efficient-predictabl
"The reasons why deepcopy is so much slower than the dict comprehension + list copy are:
- deepcopy is multi-purpose function - it works for mostly any kind of object
- deepcopy is implemented in python whilst dict comprehension and list slicing is done at lower level
And most imporantly:
- deepcopy makes copies of the elements inside containers recursively, whilst your dict comprehension does not."
But if it's the same object (after a dict comprehension spin), then it risky that it's mutable and gets changed by something that you didn't expect. That's functionally different so it can't really be compared performance-wise.
thanks a lot, so many years later, still saved me!
Me too! Changing dictionaries in a loop and couldn't find what is messing me up the resulting dictionary. THANKS!!!