Python——Copy-and-Deepcopy

deepcopy与copy的本质区别——是否为可变对象创建新的对象(内存空间)
以下图片截取自Python Tutorial


代码片段一

  • 可变对象list中包含着可变list和不可变对象tuple, 且tuple中不包含可变对象
    1
    2
    3
    4
    5
    import copy
    l1 = [3, [66, 55, 44], (7, 8, 9)]
    l2 = list(l1) # <==> l2 = copy.copy(l1)
    # <==> l2 = l1[:]
    l3 = copy.deepcopy(l1)

代码片段二

  • 可变对象list中包含着可变list和不可变对象tuple, 且tuple中包含可变对象list
    1
    2
    3
    4
    5
    import copy
    l1 = [3, [66, 55, 44], (7, 8, [1, 2])]
    l2 = list(l1) # <==> l2 = copy.copy(l1)
    # <==> l2 = l1[:]
    l3 = copy.deepcopy(l1)

代码片段三

  • 不可变对象中包含可变对象
  • 值得强调的是,copy复制tuple时,不会像list那样直接创建新对象,无论tuple中是否有可变对象*
  • 除非包含不可变对象,否则deepcopy复制tuple时也不会创建新对象*
    1
    2
    3
    4
    5
    6
    7
    import copy
    t1 = (3, [66, 55, 44], (7, 8, [1, 2]))
    t2 = t1
    t3 = tuple(t1) # <==> t4 = t1[:]
    # t5 = copy.copy(t1)
    t6 = copy.deepcopy(t1)
    t1[1].append(100)

总结

  • 对于不可变对象

    • deepcopy与copy操作一样,都不为创建新对象,而是直接引用
    • 在后面如果有修改该不可变对象的操作时再创建新对象,此时两个版本的不可变对象地址变得不同
    • 这里是Python的常态,比如tuple(tuple1)将返回一个tuple1对象的引用而不是副本,当修改tuple1时才会创建新对象
    • 因为无论如何,修改不可变对象的不可变部分都不会修改原始对象,所以为了节约内存,Python解释器完全可以将创建新对象保留到修改内容时
  • 对于可变对象

    • deepcopy将创建新对象
    • copy只复制对象地址
    • 后面修改该可变对象时地址不变,而是直接修改内容

总之
deepcopy的目的就是确保,无论如何修改,原始对象和副本之间都完全独立
所以
只要是可能被修改的对象都要复制!!!
不可变对象在复制时会自动新建
故而deepcopy时不可变对象不用创建新对象