python 引用、深拷贝、浅拷贝

python 引用、深拷贝、浅拷贝

1 相关概念

1.1 python对象

python对象是一个内存块,拥有特定的值,支持特定类型的相关操作。每个对象由:标识(identity)、类型(type)、value(值)三个部分组成,如下图所示:
在这里插入图片描述
例1:

s='abc'
print('id: ',id(s))
print('type: ',type(s))
print('value: ',s)

得到输出如下:

id: 2959051297200
type: <class ‘str’>
value: abc

1.2 引用

在 Python 中,变量存储对象的地址,变量通过地址引用对象,因此,变量也被称为对象的引用。
变量位于栈内存(压栈出栈等)。而对象位于堆内存。
·Python 是动态类型语言,变量不需要显式声明类型。根据变量引用的对象,Python 解释器自动确定数据类型
·Python 是强类型语言,每个对象都有数据类型,只支持该类型支持的操作
在这里插入图片描述

1.3 python中序列对象的存储结构,以列表为例

python中常用的序列结构有:字符串,列表,元组,字典,集合。序列是一种数据存储方式,用来存储一系列数据。在内存中,序列就是一块用来存放多个值的连续的内存空间。比如一个整数序列[1,2,3,4]。
在python3中一切皆对象,列表本身是对象,它内部存储的也是对象的地址,不是值,列表中有个元素就是几个对象。
例如,对于列表[1,2,3,4],在内存中的存储可以用下图理解:
在这里插入图片描述

1.4 深拷贝与浅拷贝

浅拷贝:重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。
深拷贝:重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。
这个描述比较抽象,下面结合实例进行理解。

2 实例理解

2.1 单层列表:引用与拷贝
list1=[1,2,3,4]
list2=list1 #引用 
list3=list1.copy() #拷贝
print('id(list1)=',id(list1))
print('id(list2)=',id(list2))
print('id(list3)=',id(list3))
list1.append(5)
print('list1:',list1)
print('list2:',list2) 
print('list3:',list3)

输出结果:

id(list1)= 1857873138184
id(list2)= 1857873138184
id(list3)= 1857873138696
list1: [1, 2, 3, 4, 5]
list2: [1, 2, 3, 4, 5]
list3: [1, 2, 3, 4,]

上述代码中的三个变量之间的关系,可以用下图的形式表示:
在这里插入图片描述
为了更好理解,可以简单粗暴地理解为下图的形式:
在这里插入图片描述

2.2 单层列表:深拷贝与浅拷贝

这里,使用copy.copy()实现浅拷贝,copy.deepcopy()实现深拷贝

import copy
list1=[1,2,3,4]
list2=copy.copy(list1) #浅拷贝
list3=copy.deepcopy(list1) #深拷贝
print('id(list1)=',id(list1))
print('id(list2)=',id(list2))
print('id(list3)=',id(list3))
list1.append(5)
print('list1:',list1)
print('list2:',list2)
print('list3:',list3)

输出结果:

id(list1)= 2204817406152
id(list2)= 2204817406024
id(list3)= 2204817457416
list1: [1, 2, 3, 4, 5]
list2: [1, 2, 3, 4]
list3: [1, 2, 3, 4]

可以看到,这个结果与2.1中的存在差异,上述代码中的三个变量之间的关系,可以用下图理解:
在这里插入图片描述
同样,可以简单粗暴地理解为下图的形式:
在这里插入图片描述

上述单层列表的实例,还不能体现出深拷贝和浅拷贝的区别,下面用嵌套列表分析。

2.3 嵌套列表:深拷贝与浅拷贝

同样,使用copy.copy()实现浅拷贝,copy.deepcopy()实现深拷贝

import copy
list1=[[1,2,3,4,5],[2,3,4,5],[6,7,8]]
list2=copy.copy(list1) #浅拷贝
list3=copy.deepcopy(list1) #深拷贝
print('id(list1)=',id(list1),', ','id(list1[0])=',id(list1[0]),', ','id(list1[0][0])=',id(list1[0][0]))
print('id(list2)=',id(list2),', ','id(list2[0])=',id(list2[0]),', ','id(list2[0][0])=',id(list2[0][0]))
print('id(list3)=',id(list3),', ','id(list3[0])=',id(list3[0]),', ','id(list3[0][0])=',id(list3[0][0]))

list1[0].append(6)
print('list1:',list1)
print('list2:',list2)
print('list3:',list3)

输出结果:

id(list1)= 2959351867272 , id(list1[0])= 2959351855432 , id(list1[0][0])= 140709595216960
id(list2)= 2959351867592 , id(list2[0])= 2959351855432 , id(list2[0][0])= 140709595216960
id(list3)= 2959351867400 , id(list3[0])= 2959351959368 , id(list3[0][0])= 140709595216960
list1: [[1, 2, 3, 4, 5, 6], [2, 3, 4, 5], [6, 7, 8]]
list2: [[1, 2, 3, 4, 5, 6], [2, 3, 4, 5], [6, 7, 8]]
list3: [[1, 2, 3, 4, 5], [2, 3, 4, 5], [6, 7, 8]]

可以看到这个结果中深拷贝与浅拷贝存在差异,上述代码中的三个变量之间的关系,可以用下图理解:
在这里插入图片描述
可以看到,对于内层列表,浅拷贝获得的list2指向与原列表list1相同的列表,而深拷贝得到的list3创建了新的列表对象,并拷贝了所有的不可变的子对象。

参考文章:
https://blog.csdn.net/ym01213/article/details/86568573

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗小芋圆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值