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

后端 未结 11 2200
温柔的废话
温柔的废话 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:45

    The GIST to take is this: Dealing with shallow lists (no sub_lists, just single elements) using "normal assignment" rises a "side effect" when you create a shallow list and then you create a copy of this list using "normal assignment". This "side effect" is when you change any element of the copy list created, because it will automatically change the same elements of the original list. That is when copy comes in handy, as it won't change the original list elements when changing the copy elements.

    On the other hand, copy does have a "side effect" as well, when you have a list that has lists in it (sub_lists), and deepcopy solves it. For instance if you create a big list that has nested lists in it (sub_lists), and you create a copy of this big list (the original list). The "side effect" would arise when you modify the sub_lists of the copy list which would automatically modify the sub_lists of the big list. Sometimes (in some projects) you want to keep the big list (your original list) as it is without modification, and all you want is to make a copy of its elements (sub_lists). For that, your solution is to use deepcopy which will take care of this "side effect" and makes a copy without modifying the original content.

    The different behaviors of copy and deep copy operations concerns only compound objects (ie: objects that contain other objects such as lists).

    Here are the differences illustrated in this simple code example:

    First

    let's check how copy (shallow) behaves, by creating an original list and a copy of this list:

    import copy
    original_list = [1, 2, 3, 4, 5, ['a', 'b']]
    copy_list = copy.copy(original_list)
    

    Now, let's run some print tests and see how the original list behave compared to its copy list:

    original_list and copy_list have different addresses

    print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
    

    elements of original_list and copy_list have the same addresses

    print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
    

    sub_elements of original_list and copy_list have the same addresses

    print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08
    

    modifying original_list elements does NOT modify copy_list elements

    original_list.append(6)
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
    

    modifying copy_list elements does NOT modify original_list elements

    copy_list.append(7)
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
    

    modifying original_list sub_elements automatically modify copy_list sub_elements

    original_list[5].append('c')
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]
    

    modifying copy_list sub_elements automatically modify original_list sub_elements

    copy_list[5].append('d')
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]
    

    Second

    let's check how deepcopy behaves, by doing the same thing as we did with copy (creating an original list and a copy of this list):

    import copy
    original_list = [1, 2, 3, 4, 5, ['a', 'b']]
    copy_list = copy.copy(original_list)
    

    Now, let's run some print tests and see how the original list behave compared to its copy list:

    import copy
    original_list = [1, 2, 3, 4, 5, ['a', 'b']]
    copy_list = copy.deepcopy(original_list)
    

    original_list and copy_list have different addresses

    print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
    

    elements of original_list and copy_list have the same addresses

    print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
    

    sub_elements of original_list and copy_list have different addresses

    print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300
    

    modifying original_list elements does NOT modify copy_list elements

    original_list.append(6)
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
    

    modifying copy_list elements does NOT modify original_list elements

    copy_list.append(7)
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
    

    modifying original_list sub_elements does NOT modify copy_list sub_elements

    original_list[5].append('c')
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
    

    modifying copy_list sub_elements does NOT modify original_list sub_elements

    copy_list[5].append('d')
    print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
    print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]
    

提交回复
热议问题