Python中的深拷贝和浅拷贝

前言

在Python中,经常涉及到数据的传递,在数据传递使用过程中,可能会发生数据被修改的问题。为了防止数据被修改,就需要在传递一个副本,即使副本被修改,也不会影响原数据的使用。为了生成这个副本,就产生了拷贝。今天就说一下Python中的深拷贝与浅拷贝的问题。

一、Python 的引用计数

首先我们要知道,Python 内不可变对象的内存管理方式是引用计数。因此,我们在谈论拷贝时,其实谈论的主要特点都是基于可变对象的。我们来看下面这段代码:

import copy

a = "lisi"
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

print ("赋值:", id(b))
print ("浅拷贝:", id(c))
print ("深拷贝:", id(d))

输出结果:
Python
因为我们这里操作的是不可变对象,Python 用引用计数的方式管理它们,所以 Python 不会对值相同的不可变对象,申请单独的内存空间。只会记录它的引用次数。

二、浅拷贝

我们先来比较一下浅拷贝和赋值在可变对象上的区别:

import copy

a = ["lisi"]
b = a
c = copy.copy(a)

print ("赋值:", id(b))
print( "浅拷贝:", id(c))

输出结果:
Python
赋值就是对物体进行贴标签操作,作用于同一物体。而浅拷贝则会创建一个新的对象,至于对象中的元素,它依然会引用原来的物体,我们再来看一段例子:

import copy

a = ["lisi"]

print ("改变前,a内部的元素id:", [id(_) for _ in a])

c = copy.copy(a)

print ("改变前,浅拷贝c内部的元素id:", [id(_) for _ in c])

a[0] = "zhangsan"

print( "改变后,a内部的元素id:", [id(_) for _ in a])
print ("改变后,浅拷贝c内部的元素id:", [id(_) for _ in c])

输出结果:
Python
操作不可变对象时,由于引用计数的特性,被拷贝的元素改变时,就相当于撕掉了原来的标签,重新贴上新的标签一样,对于我们已拷贝的元素没有任何影响。因此在操作不可变对象时,浅拷贝和深拷贝是没有区别的

三、深拷贝

深拷贝遇到可变对象,则又会进行一层对象创建,所以你操作被拷贝对象内部的可变对象,不影响拷贝对象内部的值

import copy
import json

a = [["lis"], "zhangs"]

print ("改变前,a的值", json.dumps(a, ensure_ascii=False))
print ("改变前,a内部的元素id:", [id(_) for _ in a])

d = copy.deepcopy(a)

print ("改变前,d的值", json.dumps(d, ensure_ascii=False))
print ("改变前,深拷贝d内部的元素id:", [id(_) for _ in d])

a[0][0] = "小红"
a[1] = "小明"

print ("改变后,a的值", json.dumps(a, ensure_ascii=False))
print ("改变后,d的值", json.dumps(d, ensure_ascii=False))
print ("改变后,a内部的元素id:", [id(_) for _ in a])
print ("改变后,深拷贝d内部的元素id:", [id(_) for _ in d])

输出结果:
Python

四、总结

  1. 由于 Python 内部引用计数的特性,对于不可变对象,浅拷贝和深拷贝的作用是一致的,就相当于复制了一份副本,原对象内部的不可变对象的改变,不会影响到复制对象
  2. 浅拷贝的拷贝。其实是拷贝了原始元素的引用(内存地址),所以当拷贝可变对象时,原对象内可变对象的对应元素的改变,会在复制对象的对应元素上,有所体现
  3. 深拷贝在遇到可变对象时,又在内部做了新建了一个副本。所以,不管它内部的元素如何变化,都不会影响到原来副本的可变对
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值