Python中的浅拷贝、深拷贝

Python中的浅拷贝、深拷贝

1、定义

赋值:Python中赋值语句总是创建对象的引用,而不是复制对象。因此,Python中的变量更像是指针,而不是数据储存区域。当把值赋给另一个变量的时候,Python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。
拷贝:在业务中有时我们需要复制一个对象,但是又不想对原对象产生副作用,那就不能通过赋值给新变量来解决了(赋值不是拷贝一个对象)。
浅拷贝(Shallow Copy):python拷贝一般都是浅拷贝,拷贝时,只拷贝父对象,不会拷贝对象的内部的子对象,因此,源对象与拷贝对象会引用同一个子对象。
深拷贝():使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同。
可变对象:对象的内容是可变的,如:列表、字典
不可变对象:对象的内容是不可变的,如:字符串、元组、数字

2、浅拷贝的实现

1.直接赋值

>>> a = [1,2,3]
>>> b = a
>>> b.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>> id(a)
2644782401608
>>> id(b)
2644782401608

2.切片

>>> c = [2,0,[1,9]]
>>> d = c[:]
>>> d[2][0] += 9
>>> c
[2, 0, [10, 9]]
>>> d
[2, 0, [10, 9]]
>>> id(c)
2644782518984
>>> id(d)
2644782399944
#外层地址不同
>>> id(c[2])
2644782254024
>>> id(d[2])
2644782254024
#内层地址相同

3.使用数据类型的copy

列表

>>> a=[1,2,3,['m','n']]
>>> b=a.copy()
>>> a[1]=8
>>> a
>>> b
[1, 8, 3, ['m', 'n']]
[1, 2, 3, ['m', 'n']]
#浅拷贝改变a的外层,b不会随之变化,因为他们的外层是两个独立的个体,互不影响

>>> a=[1,2,3,['m','n']]
>>> b=a.copy()
>>> a[3][0]='k'
>>> a
>>> b
[1, 2, 3, ['k', 'n']]
[1, 2, 3, ['k', 'n']]
#改变a的内层,b会随之变化,因为浅拷贝后ab的内层在一个内存地址里

字典

>>> data = {'user':'admin','num':[1,2,3]}
>>> data1 = data.copy()
>>> data
>>> data1
{'user': 'root', 'num': [1, 2, 3]}
{'user': 'admin', 'num': [1, 2, 3]}
>>> data['num'].remove(1)
>>> data
>>> data1
{'user': 'root', 'num': [2, 3]}
{'user': 'admin', 'num': [2, 3]}
#当源拷贝对象不止一级目录时,源对一级目录的子目录做任何改动,都会影响浅拷贝

4.使用 copy 模块的 copy 方法

>>> from copy import copy
>>> m = [1, 2, [3, 4]]
>>> n = copy(m)
>>> n[2][0] += 5
>>> m
>>> n
[1, 2, [8, 4]]
[1, 2, [8, 4]]

5.numpy中,传入参数为ndarray时,array()会拷贝原数据,开辟新的内存储存它,新建了一个ndarray对象。asarray与原参数共享一个内存

>>> import numpy as np
>>> x = [1,2,3,4,5,6]
>>> a = np.asarray(x)
>>> a = np.arange(3)
>>> b1 = np.asarray(a)
>>> a
>>> b1
[4 1 2]
[4 1 2]

6.numpy:ndarray.view

>>> import numpy as np
>>> e = np.array([-45,-66,2,25,99,-33])
>>> f = e.view()#f与e“共享视图”
>>> f.shape = (2,3)
>>> e[0] = 0
>>> e
array([  0, -66,   2,  25,  99, -33])
>>> f
array([[  0, -66,   2],
       [ 25,  99, -33]])
>>> f[1,1] = 88
>>> f
array([[  0, -66,   2],
       [ 25,  88, -33]])
>>> e
array([  0, -66,   2,  25,  88, -33])

3.深拷贝的实现

1.使用 copy 模块的 deepcopy 方法

import copy
>>> a = [1, 2, 3]
>>> b = copy.deepcopy(a)
>>> a
>>> b
[1, 2, 3]
[1, 2, 3]
>>> b.append(4)
>>> a
>>> b
[1, 2, 3]
[1, 2, 3, 4]
>>> id(a)
>>> id(b)
2644782458632
2644782879112

2.numpy切片与索引
使用整数序列,不和原始数组共享内存

>>> import numpy as np
>>> x = np.arange(10,1,-1)
>>> x
array([10,  9,  8,  7,  6,  5,  4,  3,  2])
>>> x[[3,3,1,8]]
array([7, 7, 9, 2])
>>> b = x[np.array([3,3,-3,8])]
>>> b
array([7, 7, 4, 2])
>>> b[2] = 100
>>> b
array([7, 7, 100, 2])
>>> x
array([10,  9,  8,  7,  6,  5,  4,  3,  2])

3.numpy:np.copy()

>>> import numpy as np
>>> e = np.array([  0, -66,   2,  25,  88, -33])
>>> g = np.copy(e)
>>> g
array([  0, -66,   2,  25,  88, -33])
>>> e[0] = 8
>>> g
array([  0, -66,   2,  25,  88, -33])
>>> id(e)
>>> id(g)
2845384560192
2845384443424

4.总结

  • 赋值一般为浅拷贝
  • 浅拷贝利用copy
  • 深拷贝利用deepcopy
  • 浅拷贝只拷贝列表的外层列表,内层列表会跟随原列表进行改变,两者互相影响
  • 深拷贝拷贝所有的数据,然后开辟了一个新的内存地址,跟原数据不在同一个地址,两者互不影响
  • numpy中的深浅拷贝有其自己的规律
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值