Python深拷贝、浅拷贝

Python中有三种拷贝:

  • =:完全不拷贝,指针指向同一块内存数据
  • copy.copy():浅拷贝,为新变量开创内存空间,但是如果变量里面有子变量,则子变量只是指向原先对应的内存空间。
  • copy.deepcopy():深拷贝,为新变量重新开创内存空间,变量里面如果有子变量也全都重新开内存来存储。

拷贝让人混淆的,一般有这几种情况:

  • 变量有子变量的情况,如v = [ [1,2], [3,4] ], 甚至v = [ [[1,2], [3,4]], [[5,6], [7,8]] ]
  • 向列表或字典插入元素的情况,如v.append(123)且时候,v的复制品是否也会变化?
  • 向列表或字典的子变量插入元素时候,复制品是否也会变化?

当变量有子变量的情况下:

import copy

original = [ [1,2], [3,4] ]

reference  = original
shallow = copy.copy(original) 
deep = copy.deepcopy(original) 

# -----RESULTS ------
# Reference >>> id(reference) == id(original)
# Shallow copy >>> id(shallow) != id(original)
# Deep copy >>> id(deep) != id(original)
#         but >>> id(deep[0]) == id(original[0])

向列表插入元素的情况下:

import copy

original = [ [1,2], [3,4] ]
reference  = original
shallow = copy.copy(original) 
deep = copy.deepcopy(original) 

original.append( [5,6] )

# -----RESULTS ------
# Original >>> original == [ [1,2], [3,4], [5,6] ]
# Reference >>> reference == [ [1,2], [3,4], [5,6] ]
# Shallow copy >>> shallow == [ [1,2], [3,4] ]
# Deep copy >>> deep == [ [1,2], [3,4] ]

为什么浅拷贝没有变化呢?
因为浅拷贝,只是拷贝了原变量的子变量的引用,也就是说,原变量增加的一个子变量,不会使浅拷贝增加一个引用。
在浅拷贝后,实际上新变量shallow中存储的内容如下:

shallow == [ address_of_[1,2], address_of_[3,4] ]

也就是说这里的逻辑关系是:只有当之前的子变量[1,2][3,4]发生变动时,变量shallow才会变化。
但是原变量original本身的扩充变化,完全和它无关了。

使用列表和字典自带的.copy()方法:
list和dict所自带的.copy()方法,实际上是浅拷贝。即如果new = original.copy(),那么这个new变量是浅拷贝出来的。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,171评论 1 32
  • 集合类型的拷贝 深拷贝是深度拷贝,是拷贝一个实例对象到一个新的内存地址,而浅拷贝只是简单拷贝一个实例对象的指针。苹...
    Longshihua阅读 500评论 0 0
  • 别闹,别闹, 嘻嘻,哈哈, 你掐疼我手指了, 你咬痛我鼻子了, 别揪我头发。 小家伙总是爱在妈妈身上乱动。 刚俯身...
    暧欣阅读 401评论 0 1
  • 这是我的读书照片 这是我的静心照片 这是我的读书照片 大花脸 大花脸 这是我的读书笔记
    洪占卿阅读 164评论 0 0
  • 初闻巴厘岛是那部电影《Eat, Pray, Love》(美食,祈祷,与恋爱), 7年前还在上大学的我,在简陋的大学...
    铁扇生活在别处阅读 1,572评论 4 10