浅谈 python 中的赋值,浅拷贝,深拷贝

浅谈 python 中的赋值,浅拷贝,深拷贝

  1. 赋值
    什么是赋值,就是把一个变量的值赋给另一个变量(好像有点废话QAQ)。如果我们从内存的角度上来看的话,赋值只是拷贝对象的引用,它们指向的是同一个地址
    这里我们要额外介绍一个知识点:可变数据类型和不可变数据类型。在 python 中可变数据类型有 list,map 等,而不可变数据类型有 int,string,tuple 等。例如在下面的例子中我们不能直接改动 string 类型。
>>> a = 'abc'
>>> a[0] = 'c'
Traceback (most recent call last):
  File "<pyshell#106>", line 1, in <module>
    a[0] = 'c'
TypeError: 'str' object does not support item assignment

介绍完数据类型的可变与不可变,我们可以开始这一节的主题赋值了。我们可以创建一个变量 a,它的类型为 list,然后我们再把 a 赋值给 b,那么我们改动 a 的时候,b 也会发生改变,这很好理解,毕竟指向的是同一地址。但这时候我们可能会冒出一个问题(其实是我当时冒出的问题),假设我们创建一个变量 a,它的类型为 int,把 a 赋值给 b,这时候我们改动 a 的值,b 的值并没有随之发生改变啊,之前不是说它们指向的是同一个地址吗?请注意,int 类型是不可变数据类型,我们改动它的时候,它就不再指向原先的地址了。话不多说,直接上代码:

# 创建一个新的变量 a, 类型是 list
>>> a = [1, 2, 3]
# 把 a 赋值给 b
>>> b = a
#此时 a 和 b 指向的是同一块地址
>>> a is b
>>> True
# 我们改变 a, b 也会发生改变
>>> a[0] = 2
>>> b
>>> [2, 2, 3]
# 如果我们建立一个 int 类型的变量a, 把它赋值给b,
#这时它们2个指向的是同一块地址。如果这时候改变 a,
#系统会另外分配一块内存储存新的值,并让 a 绑定这块
# 内存。
>>> a = 3
>>> b = a
>>> a is b
>>> True
>>> a += 2
>>> b
>>> 3
>>> a is b
>>> False
  1. 浅拷贝
    浅拷贝的定义是:重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。浅拷贝的方法有以下几种:1. 使用数据类型本身的构造器;2.对于可变的序列,还可以通过切片操作符来完成浅拷贝;3.python 提供了 copy.copy() 函数,适用于任何数据类型的浅拷贝 (这句话是不严谨的,后面会说明原因)。
# 实现浅拷贝的各种方法,仅以原对象是可变数据类型为例
>>> import copy
# 使用数据类型本身的构造器
>>> list1 = [1, 2, 3]
>>> list2 = list(list1)
# list1 和 list2 是不同对象的引用,需要与赋值区别开
>>> list1 is list2
>>> False
# 使用切片操作符
>>> list1 = [1, 2, 3]
>>> list2 = list1[:]
# 使用 copy.copy() 函数
>>> list1 = [1, 2, 3]
>>> list2 = copy.copy(list1)

但需要注意的是,浅拷贝之所以有这个“浅”字,就是因为它只拷贝了最外面的对象,但对于原对象内部的子对象只是创建了引用。这样带来的好处是很明显的,即可以节省大量的空间。但这样同时也会带来一个问题,如果原对象中的子对象都是不可变数据类型还好,因为改变这些子对象是互不影响的,原因已经在上一节介绍赋值的时候分析过;但如果子对象是可变数据类型,由于只是创建了子对象的引用,共用的还是同一片内存,这时改变原对象中子对象的值,浅拷贝出来的新对象中的对应子对象的值也会发生改变。还是话不多说上代码:

>>> import copy
>>> a = [1, 2, [1, 2]]
>>> b = copy.copy(a)
>>> a is b
>>> False
# 改变的子对象是不可变数据类型
>>> a[0] = 2
# 改变的子对象是可变数据类型
>>> a[2].append(2)
# 对 a 这个原对象直接进行改变并不会改变 b,因为 a 和 b 这2个
# 对象并不绑定同一片地址
>>> a.append(3)
>>> a
>>> [2, 2, [1, 2, 2], 3]
>>> b
>>> [1, 2, [1, 2, 2]]
  1. 深拷贝
    为了解决上述所说的浅拷贝的缺点,我们可以使用 copy.deepcopy() 来进行深拷贝。所谓深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。

  2. 补充
    其实当我们对不可变对象进行浅拷贝和深拷贝的时候,拷贝的都是原对象的引用。但当遇到不可变对象嵌套可变对象时,浅拷贝的是对原对象的引用,但深拷贝则会创建一个新的对象。

>>> import copy
>>> a = (1, 2)
>>> b = copy.copy(a)
>>> c = copy.deepcopy(a)
>>> a is b
>>> True
>>> a is c
>>> True
>>> a = (1, 2, [1, 2])
>>> b = copy.copy(a)
>>> c = copy.deepcopy(a)
>>> a is b
>>> True
>>> a is c
>>> False
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值