0

I am doing some very basic operations with Python (3.6, but also tested in Python 2.11 - behavior is the same) and dictionaries. Here is the code sample:

max_values = dict()
min_values = dict()

initial_values = {"stat": 2, "value": 5.5}

max_values["zzz"] = initial_values
min_values["zzz"] = initial_values

So far so good, when I print those dictionaries:

for key, value in max_values.items():
    print("[%s] Key [%s] -> Value [%s]" % ("max_values", key, value))

for key, value in min_values.items():
    print("[%s] Key [%s] -> Value [%s]" % ("min_values", key, value))

I get my expected results:

[max_values] Key [zzz] -> Value [{'stat': 2, 'value': 5.5}]
[min_values] Key [zzz] -> Value [{'stat': 2, 'value': 5.5}]

But if I attempt to modify with the values, for example:

min_values["zzz"]["value"] = 1.0

And do the same print again, I get:

[max_values] Key [zzz] -> Value [{'stat': 2, 'value': 1.0}]
[min_values] Key [zzz] -> Value [{'stat': 2, 'value': 1.0}]

Question is: Why was the max_values dictionary changed? I have only modified min_values, but this new key assignment for min_value dictionary also modified max_values. Am I doing something wrong?

S.G. Harmonia
  • 297
  • 2
  • 18
buuren
  • 41
  • 2
  • 4
    Assingment **_does not copy_**. Both of the dictionaries key's have a reference to the same dictionary. You need to explicitly tell Python to make a copy of `initial_values` for both keys. – Christian Dean Jul 17 '17 at 19:34
  • 1
    `max_values["zzz"] = dict(initial_values)` – Jean-François Fabre Jul 17 '17 at 19:35
  • 1
    @Jean-FrançoisFabre Or `max_values["zzz"] = initial_values.copy()`. – Christian Dean Jul 17 '17 at 19:36
  • Perhaps [this](https://stackoverflow.com/questions/19951816/python-changes-to-my-copy-variable-affect-the-original-variable) would work. It's not an exact duplicate, but it explains what assignment does in Python. – Christian Dean Jul 17 '17 at 19:40
  • @ChristianDean you are correct, it's intended functionality in Python (and I assume in other languages as well). For anyone else willing to read a bit more about the difference between assignment and copying this link can help you: https://docs.python.org/3/library/copy.html – buuren Jul 17 '17 at 21:39

4 Answers4

1

It's because the max_values and min_values are linked together. That is, they are both referencing initial_values. So if you change one you change the other. One solution would be to use deepcopy.

Cary Shindell
  • 1,336
  • 8
  • 25
0

enter image description here

As you can see from the graph, Max_value and Min_value reference to Initial_value , which means Max_value and Min_value link to the address where you create initial_value dictionary. Once you update the value inside of the initial_val, it will also show in both Max_value and Min_value.

To avoid this problem, you can use from copy import deepcopy.

my_dict = {'1': 1, '1': 2}
new_dict= deepcopy(my_dict)

In this way, it creates a new instance for your old dictionary.

Mr_U4913
  • 1,294
  • 8
  • 12
0

You have only one dict initial_values and both of your dict are refers to the same dict initial_values. You have to copy this dict to get another dict.

Try to:

max_values["zzz"] = initial_values
min_values["zzz"] = dict(initial_values)

or:

max_values["zzz"] = initial_values
min_values["zzz"] = initial_values.copy()

And now this constructions:

min_values["zzz"]["value"] = 1.0

for key, value in max_values.items():
    print("[%s] Key [%s] -> Value [%s]" % ("max_values", key, value))

for key, value in min_values.items():
    print("[%s] Key [%s] -> Value [%s]" % ("min_values", key, value))

Get expected result:

[max_values] Key [zzz] -> Value [{'stat': 2, 'value': 5.5}]
[min_values] Key [zzz] -> Value [{'stat': 2, 'value': 1.0}]
Vladyslav
  • 2,018
  • 4
  • 18
  • 44
-2

Because you gave both of the values same dictionary just look at the first two lines of your code.

Christian Dean
  • 22,138
  • 7
  • 54
  • 87
NapolyoN
  • 337
  • 3
  • 12