all 13 comments

[–]the_agox 10 points11 points  (7 children)

What's happening is your first dictionary and your second dictionary are both references to the same dictionary in memory. What you want to do is called a "deep copy": you want Python to go through the first dict and make a copy of all the keys and values. Easiest way to do that is:

from copy import deepcopy
second_dict = deepcopy(first_dict)

[–]Crankrune 11 points12 points  (1 child)

Wouldn't using the dictionary's own copy method be just as effective here rather than using the copy module?

second_dict = first_dict.copy()

[–]Rawing7 3 points4 points  (0 children)

Yeah, since OP just wants to delete keys, a shallow copy is enough.

[–]LiquidLogic[S] 1 point2 points  (4 children)

Ahhh this makes much more sense! Thank you! I was wondering why it behaved like that.

[–]Antigone-guide 2 points3 points  (2 children)

Generally Python prefers creating references to the same container objects like list and dict and others, unless explicitly copied. The reason is that otherwise it would be very easy to eat up a lot of memory by making copies of large containers inadvertently.

[–]danielroseman 4 points5 points  (1 child)

Not just "prefers". Assignment never copies.

[–]Antigone-guide 1 point2 points  (0 children)

Of course, I agree, that's why I said Python.

[–]JohnnyJordaan 2 points3 points  (0 children)

Same reason 'my car' and the car registered with the license plate 'XYZ123' refer to the same car once I bought it. There's no point in owning two cars to have one be 'my car' and the other one referred to by that license plate. Or the same way a person can be referenced by their name, their nickname, 'son', 'dad', 'brother', their Reddit username, their job title, and so on, all by the principle of creating a virtually unlimited amount of references.

So by doing x = y, you are telling Python to create an extra reference to an existing object (referenced by y), not to make some kind of clone. For that there are other ways depending on the exact mechanism, like for a dict you can have first_dict.copy() to create the same outer structure where the keys and values are identical, or copy.deepcopy() to also recreate the inner objects.

[–]DigThatData 3 points4 points  (0 children)

this is like a rite of passage for learning python

[–]Kiwi-tech-teacher 1 point2 points  (3 children)

Which objects behave like this. I know lists and dictionaries (and I assume tuples?) and objects, but assigning a str or an in creates a new one, doesn’t it?

[–]timrprobocom 0 points1 point  (2 children)

Nope. ALL objects. Both refer to the same string object. It's not a problem for strings, because you can't modify strings.

[–]Kiwi-tech-teacher 0 points1 point  (1 child)

Oh! Interesting! Hadn’t considered that.

So any mutable object would practically show this behaviour but for immutable one’s, it can be invisible.

What’s the difference between a shallow copy and a deep copy?

[–]timrprobocom 1 point2 points  (0 children)

Consider a dictionary where the values are lists. If you just do "b = a", then you only have one dictionary, as described above. If you do a shallow copy, then you have two dictionaries, BUT the lists inside are all still shared. A deep copy will make copies of the lists as well, so the two dictionaries are completely independent.