It seems as if both dictionaries are stored in the same place. But that's impossible, right?
Actually, that's exactly what's happening. Your line:
copy = dictionary1
makes copy
another name for the object already named dictionary1
. It does not create a new dictionary containing the contents of dictionary1
.
Python variables are names for objects. Setting one variable equal to another assigns the name to the object, it does not copy the object. There are various ways to do that - for one way to do a shallow copy, you can use:
copy.update(dictionary1)
Or, as Red Alert noted in the comments above, copy = dictionary1.copy()
. That's better than declaring a new empty dict and using update
.
Or, for more safety, use the copy.deepcopy
function. With the example you've shown here there would be no difference, but if your dictionary had lists or other mutable objects as values the shallow copy would copy references to the objects rather than new objects.
Some notes on mutable vs. immutable objects follow, based on the comments thread:
It is common for implementations of Python (including the only one I can talk about with accuracy, the common C implementation) to reuse objects for some immutable objects. For example, the following code in C Python will result in two references to the same object:
x = 7
y = 7
Because 7
is immutable, it is safe to do this. You can subsequently rebind x
to a different object, eg:
x = 9
This does not affect the shared object for 7
, and y
will not change. This behavior is not special to immutable objects - x = 9
rebinds the name in the same way that x = [1, 2]
would. In neither case would y
be affected. What is special is the behavior of mutable objects - code like x = [1, 2]; x.append(3)
changes the underlying object. Correct Python implementations will not reuse objects for mutable classes.
In general, you will not have to care about this implementation detail. Although it is true that x = 7; y = 7; x is y
will return True
in the C implementation of Python, code should not rely on this. Instead, it is best to write your code as if it were entirely possible that x
and y
would have different objects - you can't mutate those objects, so it should never matter. Instead, use the comparison functions like ==
- those work regardless of the implementation detail. And in fact numeric equality can easily be true in cases where object identity is not, such as x = 7; y = 7.0; x == y
.
All you actually have to worry about is whether you have other names for your mutable objects, such as:
x = [1, 2]
y = x
y.append(3)
Python variables are always references to objects, but in some cases you can work with the objects as if they were values. They aren't, but when you're doing things that are safe to do on shared objects (such as everything you can do to an integer) you don't have to care.
The one fly in this ointment is None
. None
is a singleton object - None
is in fact a reference to a single immutable instance of NoneType
. But because comparison logic can be written incorrectly, the correct way to check for None
values is in fact to rely on that singleton nature and use x is None
instead of x == None
and run the risk that x
's equality check returns a false positive. I haven't checked the implementation details to see if it's even theoretically possible to create a second object of NoneType
, but in any case nothing does.
You should make sure that when you are mutating an object, you either intend your mutations to affect all references to that object or that you make a copy first. Because it is impossible to mutate an immutable type like an int
, you don't have to worry about this with int
s, tuple
s, frozenset
s, or other built-in immutable types.