深浅copy

发布时间:2019-05-10 22:51:33编辑:auto阅读(2013)

    一. 赋值运算

    1 s1 = [1, 2, 3, ["barry", "alex"]]
    2 s2 = s1
    3 
    4 s1[0] = 111
    5 print(s1)    # [111, 2, 3, ['barry', 'alex']]
    6 print(s2)    # [111, 2, 3, ['barry', 'alex']]
    7 
    8 s1[3][0] = "abc"
    9 print(s1)    # [111, 2, 3, ['abc', 'alex']]
    10 print(s2)    # [111, 2, 3, ['abc', 'alex']]
    11 
    12 s2[1] = "askj"
    13 print(s1)    # [111, 'askj', 3, ['abc', 'alex']]
    14 print(s2)    # [111, 'askj', 3, ['abc', 'alex']]
    15 
    16 # 由上面两个示例得知, 两个列表指向的是同一个内存地址
    17 # 所以它们是完全一样的,其中一个列表内元素的改变会导致另一个列表的改变

    二. 浅拷贝 copy

    1 s3 = [1, "拷贝", True, (1, 2, 3), [123, "ak"]]
    2 s4 = s3.copy()
    3 
    4 print(id(s3), id(s4))
    5 # 2862385252936  2862385260296   id 不一样
    6 
    7 print(id(s3[1]), id(s4[1]))
    8 # 2862384610800  2862384610800   id 一样
    9 
    10 print(id(s3[-1])), id(s4[-1])
    11 # 2862385259720  2862385259720   id 一样
    12 
    13 print(id(s3[-2])), id(s4[-2])
    14 # 2862385086400  2862385086400   id 一样
    15 
    16 # 发现列表 s3 和 s4 在内存中指向不同的地址
    17 # 但是它们同一个索引位置的元素指向内存中同一个地址
    18 # 说明新列表中的元素与原列表中的元素是公用的
    19 # 
    20 # 浅 copy 只是 copy 了一个外壳
    21 
    22 a = [1, "da", [22, 33]]
    23 b = a.copy()
    24 a[-1].append(44)
    25 print(b)    # [1, "da", [22, 33, 44]]
    26 
    27 # 但是记住 a 和 b 的 id 是不一样的!
    27 # 因此对其中一个列表的增删改查不会影响另一个列表的元素
    28 # 比如接着上面
    29 a.append(33)
    30 print(a)    # [1, "da", [22, 33,44], 33]
    31 print(b)    # [1, "da", [22, 33, 44]]
    32 # 注意 a.append(33) 与 a[-1].append(44) 的区别!
    33 # 一个是给列表添加元素,另一个是给列表中的元素(即列表)里添加一个元素
    34
    35
    37 # 这里涉及到切片的相关知识
    38 l1 = [1, 2, 3, [22, 33]]
    39 l2 = l1[::]
    40 l1[-1].append(666)
    41 print(l2)   # [1, 2, 3, [22, 33, 666]
    42 # 这说明对列表创建一个副本是 浅copy!

    三. 深拷贝 copy

    1 import copy
    2 
    3 s5 = [3, True, "ask", (1, 2, 3), [34, "as"]]
    4 s6 = copy.deepcopy(s5)
    5 
    6 print(id(s5), id(s6))  
    7 # 2862386662664  2862386819848
    8 
    9 print(id(s5[0]), id(s6[0]))  
    10 # 1409182528  1409182528
    11 
    12 print(id(s5[-1]), id(s6[-1]))  
    13 # 2862386662600  2862386819912
    14 
    15 print(id(s5[-2]), id(s6[-2]))  
    16 # 2862385217680  2862385217680
    17 
    18 # 对于深copy,列表是在内存中重新创建的。
    19 # 列表中可变的数据类型是重新创建的,列表中的不可变数据类型是公用的

    注意:

    1、深浅copy的补充
    a = [1, 2, [33, 44]]
    
    b = [1, 2, [33, 44]]  # 新建一个所有元素相同的列表是  深copy
    c = [::]  # 全切一个列表得到的列表是  浅copy
    2、虽然深浅copy,两个对象的不可变数据类型元素id都相同,但是修改其中一个对象的不可变数据类型元素,并不会影响另一个对象相同id元素的值。
    # 浅copy
    l1 = [1, 'alex', [11,22]]
    l2 = l1.copy()
    l1[0] = 1000
    print(l1)  # [1000, 'alex', [11, 22]]
    print(l2)  # [1, 'alex', [11, 22]]
    # 深copy
    import copy
    l1 = [1, 'alex', [11,22]]
    l2 = copy.deepcopy(l1)
    l1[0] = 1000
    print(l1)  # [1000, 'alex', [11, 22]]
    print(l2)  # [1, 'alex', [11, 22]]

    面试题

    # 求l2的打印结果?
    l1 = [1,2,3,[22,33]]
    l2 = l1[::]
    l1[-1].append(666)
    print(l2)
    # 打印结果为:
    [1, 2, 3, [22, 33, 666]]
    
    # 全切得到的列表是对原列表的浅copy
    print(id(l1[0]), id(l2[0]))  # 不可变数据类型元素的id一样
    print(id(l1[-1]), id(l2[-1]))  # 可变数据类型元素的id一样

关键字