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 comment
aRkadeFR

wow... thanks for the post :)

ëRiC

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)

Peter Hansen

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.)

James

Awesome post thank you

David

Thank YOU so much!

Ilya Rusin

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."

Peter Bengtsson

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.

Jan

thanks a lot, so many years later, still saved me!

Kai Franke

Me too! Changing dictionaries in a loop and couldn't find what is messing me up the resulting dictionary. THANKS!!!

Your email will never ever be published.

Previous:
Examples of mozjpeg savings September 1, 2015 Web development, Mozilla
Next:
peepin - a great companion to peep September 10, 2015 Python
Related by category:
How I run standalone Python in 2025 January 14, 2025 Python
get in JavaScript is the same as property in Python February 13, 2025 Python
How to resolve a git conflict in poetry.lock February 7, 2020 Python
Best practice with retries with requests April 19, 2017 Python
Related by keyword:
Fastest way to uniquify a list in Python >=3.6 December 23, 2017 Python
Shallow clone vs. deep clone, in Node, with benchmark September 29, 2023 Node, JavaScript
An example of using Immer to handle nested objects in React state January 18, 2019 React, JavaScript
When to __deepcopy__ classes in Python March 14, 2012 Python