I’m coming from C, learning Python. In Python (3.5.2), it seems that assignment of one data type to another of the same type is sometimes done by value and sometimes by reference.
For example, strings are assigned by value:
>>> str1 = "hello" >>> str2 = str1 >>> print(str1, str2) hello hello >>> str2 = "goodbye" >>> print(str1, str2) hello goodbye
This is the behavior I expect. However, it works differently with dictionaries:
>>> dict1 = {'key1':'val1', 'key2':'val2'} >>> dict2 = dict1 >>> print(dict1, dict2) {'key2': 'val2', 'key1': 'val1'} {'key2': 'val2', 'key1': 'val1'} >>> dict2['key1'] = 'newval' >>> print(dict1, dict2) {'key2': 'val2', 'key1': 'newval'} {'key2': 'val2', 'key1': 'newval'}
Notice that both dict1
and dict2
were changed. Similarly, if I add a key/value pair to either of the dictionaries it will appear in both. Argh!
(sorry, that was my C-background speaking) :)
How am I to know which behavior to expect for any given variable type? Is there a method to this madness or will I simply need to remember arbitrary rules?
P.S. I realize I can get my expected behavior by using dict2 = dict(dict1)
.
The “possible duplicate” contains good info on how to do it, but I’m interested in why I have to. The answers to this question are already very helpful!
Advertisement
Answer
In Python, everything is by reference; This is different from C, variable is not a box. The assignment is actually a binding.
str1 = "hello" str2 = str1
Both str1
and str2
reference to “hello”, but string in Python is immutable, so modifying str2
, would creating a new binding, and hence do not affect the value of str1
str2 = "hack" # here str1 will still reference to "hello" object
Dict works the same:
d1 = {"name": "Tom"} d2 = d1
d2
and d1
will reference the same object. If change d2
to a new value do not affect the value of d1
; But instead, if we only modify d2
in place, like d2['age'] = 20
, the value of d1
would be changed since they share the same object.
d2 = {"name": "Hack"} # the value of d1 does not change
Luciano Ramalho summarized it in Fluent Python, Chapter 8, Variables Are Not Boxes section
To understand an assignment in Python, always read the righthand side first: that’s where the object is created or retrieved. After that, the variable on the left is bound to the object, like a label stuck to it. Just forget about the boxes.