pythoniterablerefer

Python - How to avoid refer multiple names to one dict


I am struggling with python dictionary. I have two dics named defaultSettings and personalSettings. I want to make function sets personalSettings's values to defaultSettings's values. But I don't want to all changes be applied to defaulSettings.

I tried this code:

defaultSettings = {'s1': 1, 's2':2, 's3':3}

personalSettings = {'s1': 3, 's2':2, 's3':1}

print(defaultSettings)
print(personalSettings)
print('-*-*-*-*-*-*-*-*-*-*-*-*')

personalSettings = defaultSettings

print(defaultSettings)
print(personalSettings)
print('-*-*-*-*-*-*-*-*-*-*-*-*')

personalSettings['s1'] = 5

print(defaultSettings)
print(personalSettings)

And my output is:

{'s1': 1, 's2': 2, 's3': 3}
{'s1': 3, 's2': 2, 's3': 1}
-*-*-*-*-*-*-*-*-*-*-*-*
{'s1': 1, 's2': 2, 's3': 3}
{'s1': 1, 's2': 2, 's3': 3}
-*-*-*-*-*-*-*-*-*-*-*-*
{'s1': 5, 's2': 2, 's3': 3}
{'s1': 5, 's2': 2, 's3': 3}
-*-*-*-*-*-*-*-*-*-*-*-*

If I change a value of personalSettings after personalSettings = defaultSettings, defaultSettings's value changes too. I know this;

enter image description here

But I don't know how avoid this or other way.


Solution

  • Consider

    >>> defaults = {'foo': 'bar', 'bee': 'blah'}
    >>> actual = dict(defaults)
    >>> actual['foo'] = 'BAZ'
    >>> defaults
    {'foo': 'bar', 'bee': 'blah'}
    >>> actual
    {'foo': 'BAZ', 'bee': 'blah'}
    

    The trick is actual = dict(defaults). This way actual can be changed without affecting defaults.

    If your dicts have sub-objects, consider deepcopy or json.dumps/loads to make a deep copy:

    >>> myDict = {'s1':1,  's2':{'b1':2, 'b2':3}}
    >>>
    >>> from copy import deepcopy
    >>>
    >>> myDict2 = deepcopy(myDict)
    >>>
    >>> myDict2['s2']['b1'] = 99
    >>>
    >>> myDict
    {'s1': 1, 's2': {'b1': 2, 'b2': 3}}
    >>> myDict2
    {'s1': 1, 's2': {'b1': 99, 'b2': 3}}