Today in the writing code encountered a wonderful problem, the problem is described as follows:
The code declares a list, passes the list as a parameter into function1 (), and Del () in function1 () deletes an element.
Function2 () also used the list as a parameter, after the call to Function1 () and then call function2 () there is a problem, the list value has been changed, there is a bug.
Directly on the code:
List = [0, 1, 2, 3, 4, 5]def function1 (list): del list[1] Print(list)def function2 (list): print(list) function1 ( List) function2 (list)
I do not want the list in function2 () to change, check the solution is that you can copy the list:
NewList = list.copy () function2 (newlist)
In the process of finding a solution, there is another method called deepcopy (), so the question is, what is the difference between deepcopy () and copy ()?
First point to the source code to see the next source, found that there are comments, very happy. Comments are as follows:
"""Generic (Shallow and deep) copying operations. Interface summary:import Copy x = copy.copy (y) # make a shallow copy of y x = copy.deepcopy (y # make a deep copy of Yfor module specific errors, copy. Error is raised. The difference between shallow and deep copying are only relevant Forcompound objects (objects this contain other objects, Like lists Orclass instances).-A shallow copy constructs a new compound object and then (to the extent possible) inserts *the same objects* into it is the original contains.-a deep copy constructs a new compound object and then, recursive Ly, inserts *copies* into it's the objects found in the original. The problems often exist with the deep copy operations that don ' t existwith shallow copy operations:a) recursive objects (COM Pound objects, directly or indirectly, contain a reference to themselves) may cause a recursive loop B) because de EP Copy copies *everything* it may copy too much, e.g. Administrative dataStructures that should be shared even between Copiespython's deep copy operation avoids these problems by:a) keeping a Table of objects already copied during the current copying pass B) Letting user-defined classes override the copying O Peration or the set of Copiedthis version does not copy types like module, class, function, Method,nor stack Trace, stack frame, nor file, socket, window, nor array, norany similar types. Classes can use the same interfaces-control copying that they useto control Pickling:they can define methods called __ Getinitargs__ (), __getstate__ () and __setstate__ (). See the documentation for module "Pickle" For information on these methods."""
However, looking at, a face confused force. Or Baidu continue to check the information it:
Https://iaman.actor/blog/2016/04/17/copy-in-python The big guy summed up very well.
Copy is actually shallow copy, which is in contrast to the deep copy
Conclusion:
1. There is no difference between simple object,shallow copy and deep copy
Import copy>>> origin = 1>>> Cop1 =#Cop1 is Origin's shallow copy>>& Gt COP2 =#Cop2 is Origin's deep copy>>> origin = 2>>> Origin2>>& Gt cop11>>> cop21#Cop1 and COP2 will not change their values with Origin >>> Cop1 ==< c13> cop2true is cop2true
2. Complex object, such as the list in the case of the list,shallow copy in the sub-list, not from the original object really "independent" out.
If you change an element in the child list of the original object, your copy will change along with it. This is different from our intuitive understanding of "copy".
>>>ImportCopy>>> origin = [1, 2, [3, 4]]#There are three elements inside Origin: 1, 2,[3, 4]>>> COP1 =Copy.copy (Origin)>>> COP2 =Copy.deepcopy (Origin)>>> COP1 = =cop2true>>> COP1 isCop2false#Cop1 and Cop2 look the same, but they are no longer the same object>>> Origin[2][0] ="hey!">>>origin[1, 2, ['hey!', 4]]>>>cop1[1, 2, ['hey!', 4]]>>>cop2[1, 2, [3, 4]]#Change the Sub list in Origin [3, 4] to an element, observing Cop1 and COP2
cop1
, that is, shallow copy followed the origin change. And cop2
, that is, deep copy does not change.
Then the question comes again, there is deepcopy direct use is good why still have copy?
The solution to this problem is to start with the method of storing the Python variable, in Python, rather than assigning a value to a variable, rather than giving the variable a reference (reference) to a specific value .
>>> a = [1, 2, 3]>>> b = a>>> a = [4, 5, 6]// assigns a new value to a>>>
a[4, 5, 6
]>>>
b[1, 2, 3
]
#
After the value of a changes, B does not follow a change >>> a = [1, 2, 3
]>>> b =
a>>> a[0], a[1], a[2] = 4, 5, 6//
change the elements in the original list >> ;>
a[4, 5, 6
]>>>
b[4, 5, 6
]
#
a changed the value of B as a changed
The above code has changed the value of a, the difference is: the first paragraph is to give a new value, the second paragraph is a direct change in the list of elements.
Here's an explanation of the strange phenomenon:
As an item for the first time [1, 2, 3]
. a = [1, 2, 3]
it's equivalent to labeling this item a
. And that b = a
is to put a label on the item b
.
First case:
a = [4, 5, 6]
It's the equivalent of a
tearing the label from [1 ,2, 3]
top to [4, 5, 6]
top.
In the process, [1, 2, 3]
the item did not disappear. b
from beginning to finish the good stick on [1, 2, 3]
, since this reference also has not changed. b
the value is not changed naturally.
Second case:
a[0], a[1], a[2] = 4, 5, 6
The item itself is changed directly [1, 2, 3]
. Re-modified every part of it inside. After the internal modification, it [1, 2, 3]
became itself [4, 5, 6]
.
And in the process, a
and none b
moved, they also posted on the item. So a
b
The value of nature has become [4, 5, 6]
.
用copy.copy()
。 It turns out that the ontology and copy are not independent. Sometimes you change one and the other changes. This is the example mentioned at the beginning of this article:
>>>ImportCopy>>> origin = [1, 2, [3, 4]]#There are three elements inside Origin: 1, 2,[3, 4]>>> COP1 =Copy.copy (Origin)>>> COP2 =Copy.deepcopy (Origin)>>> COP1 = =cop2true>>> COP1 isCop2false#Cop1 and Cop2 look the same, but they are no longer the same object>>> Origin[2][0] ="hey!">>>origin[1, 2, ['hey!', 4]]>>>cop1[1, 2, ['hey!', 4]]>>>cop2[1, 2, [3, 4]]#Change the Sub list in Origin [3, 4] to an element, observing Cop1 and COP2
Official explanation:
The difference between shallow andDeep copying isOnly relevant forCompound objects (objects that contain other objects, like listsor classinstances): A shallow copy constructs a new compound object andThen, to the extent possible, inserts references into it to the objects foundinchThe original. A deep copy constructs a new compound object andThen, recursively, inserts copies into it of the objects foundinchThe original. Two copy differs only in the face of complex objects, so-called complex objects, which refer to objects with other objects such as complex lists andclass). In a new complex object created by shallow copy, each sub-object simply points to its own sub-object in the original ontology. In the complex object built by deep copy, the copy of the object is stored, and the layers are copied to the end.
First look at the shallow copyhere. , Cop1 a mirror for the origin of the time. The elements in Origin point to where the elements in the COP1 point. This is what the official doc says inserts references into it to the objects found in the original
.
The key here is, that is, origin[2]
[3, 4] this list. According to the definition of shallow copy , the cop1[2]
point is the same list [3, 4]. Well, if we change this list here, it will cause both origin and cop1 to change at the same time. That's why the origin[2][0] = "hey!"
Cop1 has become a thing of the top [1, 2, [‘hey!‘, 4]]
.
See Deep copyagain. As you can see, COP2 is storing a copy of origin on each floor. At origin[2]
cop2[2]
this time and although the value is equal to [3, 4], but it is not the same list.
Since it is completely independent, it will change one of them anyway, and the other won't change naturally.
Shallow copy and deep copy in Python