python深浅拷贝

  • 缘起

  • 背景

    • 众所周知, python默认进行浅拷贝, 而深拷贝需要动用copy模块下的copy.deepcopy
    • 深浅拷贝的实质区别在于是否生成了新的对象, 深拷贝生成了新的对象, 浅拷贝在同一个对象上增加了一个引用
    • 不同对象可以由id进行区分
  • 结论

    • deepcopy作用于容器时, 深拷贝是递归进行的
    • copy.copy作用于容器时
      • 容器是可变对象, 此时copy.copy只对第一层进行深拷贝, 其余浅拷贝
      • 容器是不可变对象, 此时copy.copy对容器整体进行浅拷贝
  • 演示

import copy
# l for list

l1,l2=[1,2,3],[1,2,3]
print('l1:{};\tl2:{}'.format(id(l1),id(l2)))
l12=[l1,l2]

d_l12=copy.deepcopy(l12)

print('l12:{};\td_l12:{}'.format(id(l12),id(d_l12))) # deepcopy外壳实现了深拷贝
print('l1:{};\tl12元素0:{};\td_l12元素0:{}'.format(id(l1),id(l12[0]),id(d_l12[0]))) # deepcopy内部元素同样也实现了深拷贝:l12的元素0就是l1对象本身; 而d_l12元素0不是l1对象
# 由于l2也是同样的情况, 所以就不演示了

# cc for copy_copy obj

cc_l12=copy.copy(l12)

print('l12:{};\tcc_l12:{}'.format(id(l12),id(cc_l12))) # 对l12可变对象: copy.copy外壳实现了深拷贝
print('l1:{};\tl12元素0:{};\tcc_l12元素0:{}'.format(id(l1),id(l12[0]),id(cc_l12[0]))) # copy.copy内部元素仅仅实现了浅拷贝:l12的元素0就是l1对象本身; 而cc_l12元素0也是l1对象本身

# t for tuple
t12=(l1,l2)
cc_t12=copy.copy(t12)
print('t12:{};\tcc_t12:{}'.format(id(l12),id(cc_l12))) # 对t12可变对象: copy.copy外壳仅实现浅拷贝
print('l1:{};\tt12元素0:{};\tcc_t12元素0:{}'.format(id(l1),id(l12[0]),id(cc_l12[0]))) # copy.copy内部元素也仅仅实现了浅拷贝:t12的元素0就是l1对象本身; 而cc_t12元素0也是l1对象本身
  • 图示

  • 例外事项(2019年8月24日 补充)

    • 昨日学弟问起函数对象为何无法进行深拷贝的问题,以下是代码:
import copy
def greet():
print('hw.')
d_greet=copy.deepcopy(greet)
print('greetID:{};\td_greetID:{}'.format(id(greet),id(d_greet))) # 可以看出id是一致的, 说明没有完成深复制
- 能有这样的意识, 其实已经说明该学弟python水平已经非同小可了(甚至想推荐他学一波lambda演算~
- 然而, 文档的重要性还是要继续重申, 以下文档中搜索"unchanged"就可以查到:[It does “copy” functions and classes (shallow and deeply) by returning the original object](`https://web.archive.org/web/20220605125945/https://docs.python.org/3/library/copy.html`)
  • 感言
    • 后生可畏, 中年失业什么的还是尽早有准备和觉悟才好.
    • 文档的重要性还是要多重申几次呀, 不要因为库的局限性而浪费了自己的时间, 甚至于怀疑自身的逻辑性什么的真是大可不必.