I once came across a question like this: an element in a dictionary is a list. Assign this list element to a variable, then modify the value of an element in the list. As a result, the list in the dictionary was also modified. The question was as follows:
dict = {'a':[1,2,3,4,5],'b':2}
x = dict['a']
for i in range(5):
x[i] = 0
print(dict['a'])
The program output is as follows: [0, 0, 0, 0, 0]
This involves the question of whether Python assignment is by reference or by copy, i.e., whether assignment passes by value or by address. In the above problem, assigning the value of "a" to x caused the above situation. If the value of "b" were assigned to x, then when we modify the value of x, the value of the dict dictionary would not be affected.
>>> dict = {'a':[1,2,3,4,5],'b':2}
>>> x = dict['b']
>>> x
2
>>> x=x+3
>>> x
5
>>> dict
{'a': [1, 2, 3, 4, 5], 'b': 2}
>>>
So the question arises: under what circumstances does variable assignment pass by value (copy), and under what circumstances does it pass by address (reference)?
1. Direct Copy
When we are unsure whether it is a reference or a copy, we can explicitly copy. For example, dictionary objects themselves have a copy method:
x=dict.copy()
Objects without a copy method can also be copied. Here we introduce the concept of deep copy. Deep copy is a deepcopy method provided by Python's copy module. Deep copy completely copies all data associated with the original variable and generates an identical set of content in memory. In this process, any modification we make to one of the two variables will not affect the other variable. Using the same code as above, if we change it to the following:
import copy
dict = {'a':[1,2,3,4,5],'b':2}
x = copy.deepcopy(dict['a'])
for i in range(5):
x[i] = 0
print(dict['a'])
The output shows that the dict value is not affected.
In addition to deep copy, the copy module also provides a copy method, known as shallow copy. For simple objects, deep copy and shallow copy are the same. The copy method of the dictionary object above is a shallow copy.
>>> dict
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd=copy.copy(dict)
>>> dd
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd['a'][0]=7
>>> dd
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee=dict.copy()
>>> ee
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee['a'][0]=9
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> ee['b']=5
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 5}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>>
With shallow copy, changes to the first level do not affect each other (such as modifying the value of dict b in the above example), while changes to the second level (such as modifying the list value of dict a in the above example) do affect each other — modify one, and the others change along with it. Let's look at the id:
>>> id(dict) 20109472 >>> id(dd) 20244496 >>> id(ee) 20495072 >>> id(dd['a']) 20272112 >>> id(ee['a']) 20272112 >>> id(dict['a']) 20272112 >>>
It can be seen that the ids of the various dictionary copies are different, but the ids of the values in dict a are the same. If we need a true copy, use deep copy.
2. Passing Rules
Python assignment does not explicitly distinguish between copy and reference. Generally, passing of static variables is by copy, and passing of dynamic variables is by reference. (Note: the first pass of a static variable is also by reference. When the static variable needs to be modified, since it cannot be changed, a new space needs to be created to store data.)
- Strings, numbers, and tuples are all static variables.
- Lists and dictionaries are dynamic variables.
Variables are sometimes complex, and combinations can occur, such as a dictionary containing a list, or a list containing a dictionary. But when assigning, it always belongs to a certain type. If you are really unsure of the situation, you can test it using the id() function. If it is a reference, the addresses pointed to by the two variables are the same. For example:
>>> a=6 >>> id(a) 10413476 >>> b=a >>> id(b) 10413476 >>> b=8 >>> id(b) 10413452 >>>
Before modifying variable b, a and b point to the same address. After modifying b, the address changes.
Original link: https://blog.csdn.net/iamlaosong/article/details/77505510