LIST与ndarray赋值陷阱,深拷贝出独立的对象

问题:赋值后改变一个ndarray,另外一个ndarray也会受影响

a = [1,2,3]
P = np.asarray(a)
temp = P
temp[0] = 100
print(P)  # [100   2   3]

list也一样:

a = [1,2,3]
temp = a
temp[0] = 100
print(a)  # [100, 2, 3]

解决:使用深拷贝deepcopy():

import copy

a = [1,2,3]
temp = copy.deepcopy(a)
temp[0] = 100
print(a)  # [1, 2, 3]
print(temp)  # [100, 2, 3]

 

python中list的赋值操作主要有三种,‘=’、拷贝(浅拷贝copy)和深拷贝(deepcopy),下面结合例子来说明这三种操作:

1)‘=’:

用等号来赋值,新的变量和原来的变量实际上指向的是同一个地址,等号连接起来的变量互相影响,看如下的操作:Alice用等号与testlist连接后,对Alice的改变会直接影响到原列表以及与之相连的Bob,也就是说Alice、Bob和testlist都指向同一地址,对任意一个的修改都会影响到其他两个变量

2)浅拷贝copy:


拷贝原list变量的第一层,之后对新变量或者旧变量的第一层的修改不会影响到彼此,第二层以及更多层之间则是像第一中操作中一样,是互相影响的。什么是第一层呢,例如:

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

那么1,2,[3,4]都属于第一层的元素,在新变零中修改第一层的元素不会影响到原变量,同样,在原变量中修改第一层的元素也不会影响到新变量;而3,4属于第第二层中的元素,对他们修改会影响到用浅拷贝连接起来的所有变量中的第二层元素: 

import copy
testlist =[1,2,[3,4]]

Alice = copy.copy(testlist)
Bob   = copy.copy(testlist)

testlist[0] =0
testlist[2][0]=9

print('testlist=',testlist)  # testlist= [0, 2, [9, 4]]
print('Alice   =',Alice)     # Alice   = [1, 2, [9, 4]]
print('Bob     =',Bob)       #  Bob   = [1, 2, [9, 4]]

浅拷贝会创建新对象,其内容是原对象的引用。

        浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数。比如对上述a:        

        1、切片操作:b = a[:]   或者 b = [each for each in a]

        2、工厂函数:b = list(a)

        3、copy函数:b = copy.copy(a)

        浅拷贝产生的b不再是a了,使用is可以发现他们不是同一个对象,使用id查看,发现它们也不指向同一片内存。但是当我们使用 id(x) for x in a 和 id(x) for x in b 时,可以看到二者包含的元素的地址是相同的。

        在这种情况下,a和b是不同的对象,修改b理论上不会影响a。比如b.append([4,5])。

是要注意,浅拷贝之所以称为浅拷贝,是它仅仅只拷贝了一层,在a中有一个嵌套的list,如果我们修改了它,情况就不一样了。

        a[4].append("C")。查看b,你将发现b也发生了变化。这是因为,你修改了嵌套的list。修改外层元素,会修改它的引用,让它们指向别的位置,修改嵌套列表中的元素,列表的地址并为发生变化,指向的都是同一个位置

3)深拷贝(deep copy)

        深拷贝只有一种形式,copy模块中的deepcopy函数。

temp = copy.deepcopy(a)

        和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因而,它的时间和空间开销要高。

        同样对la,若使用b = copy.deepcopy(a),再修改b将不会影响到a了。即使嵌套的列表具有更深的层次,也不会产生任何影响,因为深拷贝出来的对象根本就是一个全新的对象,不再与原来的对象有任何关联。

四、关于拷贝操作的警告

        1、对于非容器类型,如数字,字符,以及其它“原子”类型,没有拷贝一说。产生的都是原对象的引用。

        2、如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。


REF:

https://blog.csdn.net/lovelyaiq/article/details/55102518 

https://blog.csdn.net/dpengwang/article/details/79240551


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值