What is the difference between shallow copy, deepcopy and normal assignment operation?

后端 未结 11 2118
温柔的废话
温柔的废话 2020-11-21 07:11
import copy

a = \"deepak\"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}

a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)


prin         


        
相关标签:
11条回答
  • 2020-11-21 07:19

    For immutable objects, creating a copy don't make much sense since they are not going to change. For mutable objects assignment,copy and deepcopy behaves differently. Lets talk about each of them with examples.

    An assignment operation simply assigns the reference of source to destination e.g:

    >>> i = [1,2,3]
    >>> j=i
    >>> hex(id(i)), hex(id(j))
    >>> ('0x10296f908', '0x10296f908') #Both addresses are identical
    

    Now i and j technically refers to same list. Both i and j have same memory address. Any updation to either of them will be reflected to the other. e.g:

    >>> i.append(4)
    >>> j
    >>> [1,2,3,4] #Destination is updated
    
    >>> j.append(5)
    >>> i
    >>> [1,2,3,4,5] #Source is updated
    

    On the other hand copy and deepcopy creates a new copy of variable. So now changes to original variable will not be reflected to the copy variable and vice versa. However copy(shallow copy), don't creates a copy of nested objects, instead it just copies the reference of nested objects. Deepcopy copies all the nested objects recursively.

    Some examples to demonstrate behaviour of copy and deepcopy:

    Flat list example using copy:

    >>> import copy
    >>> i = [1,2,3]
    >>> j = copy.copy(i)
    >>> hex(id(i)), hex(id(j))
    >>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different
    
    >>> i.append(4)
    >>> j
    >>> [1,2,3] #Updation of original list didn't affected copied variable
    

    Nested list example using copy:

    >>> import copy
    >>> i = [1,2,3,[4,5]]
    >>> j = copy.copy(i)
    
    >>> hex(id(i)), hex(id(j))
    >>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different
    
    >>> hex(id(i[3])), hex(id(j[3]))
    >>> ('0x10296f908', '0x10296f908') #Nested lists have same address
    
    >>> i[3].append(6)
    >>> j
    >>> [1,2,3,[4,5,6]] #Updation of original nested list updated the copy as well
    

    Flat list example using deepcopy:

    >>> import copy
    >>> i = [1,2,3]
    >>> j = copy.deepcopy(i)
    >>> hex(id(i)), hex(id(j))
    >>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different
    
    >>> i.append(4)
    >>> j
    >>> [1,2,3] #Updation of original list didn't affected copied variable
    

    Nested list example using deepcopy:

    >>> import copy
    >>> i = [1,2,3,[4,5]]
    >>> j = copy.deepcopy(i)
    
    >>> hex(id(i)), hex(id(j))
    >>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different
    
    >>> hex(id(i[3])), hex(id(j[3]))
    >>> ('0x10296f908', '0x102b9b7c8') #Nested lists have different addresses
    
    >>> i[3].append(6)
    >>> j
    >>> [1,2,3,[4,5]] #Updation of original nested list didn't affected the copied variable    
    
    0 讨论(0)
  • 2020-11-21 07:23

    In python, when we assign objects like list, tuples, dict, etc to another object usually with a ' = ' sign, python creates copy’s by reference. That is, let’s say we have a list of list like this :

    list1 = [ [ 'a' , 'b' , 'c' ] , [ 'd' , 'e' , 'f' ]  ]
    

    and we assign another list to this list like :

    list2 = list1
    

    then if we print list2 in python terminal we’ll get this :

    list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]
    

    Both list1 & list2 are pointing to same memory location, any change to any one them will result in changes visible in both objects, i.e both objects are pointing to same memory location. If we change list1 like this :

    list1[0][0] = 'x’
    list1.append( [ 'g'] )
    

    then both list1 and list2 will be :

    list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g'] ]
    list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g’ ] ]
    

    Now coming to Shallow copy, when two objects are copied via shallow copy, the child object of both parent object refers to same memory location but any further new changes in any of the copied object will be independent to each other. Let’s understand this with a small example. Suppose we have this small code snippet :

    import copy
    
    list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]      # assigning a list
    list2 = copy.copy(list1)       # shallow copy is done using copy function of copy module
    
    list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1
    
    print list1
    list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
    list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]
    

    notice, list2 remains unaffected, but if we make changes to child objects like :

    list1[0][0] = 'x’
    

    then both list1 and list2 will get change :

    list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
    list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] ]
    

    Now, Deep copy helps in creating completely isolated objects out of each other. If two objects are copied via Deep Copy then both parent & it’s child will be pointing to different memory location. Example :

    import copy
    
    list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]         # assigning a list
    list2 = deepcopy.copy(list1)       # deep copy is done using deepcopy function of copy module
    
    list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1
    
    print list1
    list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
    list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]
    

    notice, list2 remains unaffected, but if we make changes to child objects like :

    list1[0][0] = 'x’
    

    then also list2 will be unaffected as all the child objects and parent object points to different memory location :

    list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
    list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f  ' ] ]
    

    Hope it helps.

    0 讨论(0)
  • 2020-11-21 07:24

    Not sure if it mentioned above or not, but it's very importable to undestand that .copy() create reference to original object. If you change copied object - you change the original object. .deepcopy() creates new object and does real copying of original object to new one. Changing new deepcopied object doesn't affect original object.

    And yes, .deepcopy() copies original object recursively, while .copy() create a reference object to first-level data of original object.

    So the copying/referencing difference between .copy() and .deepcopy() is significant.

    0 讨论(0)
  • 2020-11-21 07:30

    For immutable objects, there is no need for copying because the data will never change, so Python uses the same data; ids are always the same. For mutable objects, since they can potentially change, [shallow] copy creates a new object.

    Deep copy is related to nested structures. If you have list of lists, then deepcopy copies the nested lists also, so it is a recursive copy. With just copy, you have a new outer list, but inner lists are references.

    Assignment does not copy. It simply sets the reference to the old data. So you need copy to create a new list with the same contents.

    0 讨论(0)
  • 2020-11-21 07:30

    Deep copy is related to nested structures. If you have list of lists, then deepcopy copies the nested lists also, so it is a recursive copy. With just copy, you have a new outer list, but inner lists are references. Assignment does not copy. For Ex

    import copy
    spam = [[0, 1, 2, 3], 4, 5]
    cheese = copy.copy(spam)
    cheese.append(3)
    cheese[0].append(3)
    print(spam)
    print(cheese)
    

    OutPut

    [[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Copy method copy content of outer list to new list but inner list is still same for both list so if you make changes in inner list of any lists it will affects both list.

    But if you use Deep copy then it will create new instance for inner list too.

    import copy
    spam = [[0, 1, 2, 3], 4, 5]
    cheese = copy.deepcopy(spam)
    cheese.append(3)
    cheese[0].append(3)
    print(spam)
    print(cheese)
    

    Output

    [0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]

    0 讨论(0)
  • 2020-11-21 07:33
    >>lst=[1,2,3,4,5]
    
    >>a=lst
    
    >>b=lst[:]
    
    >>> b
    [1, 2, 3, 4, 5]
    
    >>> a
    [1, 2, 3, 4, 5]
    
    >>> lst is b
    False
    
    >>> lst is a
    True
    
    >>> id(lst)
    46263192
    
    >>> id(a)
    46263192 ------>  See here id of a and id of lst is same so its called deep copy and even boolean answer is true
    
    >>> id(b)
    46263512 ------>  See here id of b and id of lst is not same so its called shallow copy and even boolean answer is false although output looks same.
    
    0 讨论(0)
提交回复
热议问题