python list初始化中,修改一个值,一列都修改了?延伸copy与deepcopy

今天遇到一个list初始化的问题。
初始化一个5×5的二维数组:

>>>a = [[1] * 5]*5
>>>a
[[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]

下面对a[0][0]的值进行修改:

>>> a[0][0]=10
>>> a
[[10, 1, 1, 1, 1], [10, 1, 1, 1, 1], [10, 1, 1, 1, 1], [10, 1, 1, 1, 1], [10, 1, 1, 1, 1]]

发现为什么这一列的值都修改了?百思不得其姐!查阅资料

原因在于a = [[1]*5]*5后面的四行其实是对第一行的引用。

正常情况下应该这样:

>>> a = [[1 for _ in range(5)] for _ in range(5)]#这里是重新开辟的空间,而上面是引用
>>> a
[[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]
>>> a[0][0] = 8
>>> a
[[8, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]

文档里面有写
What has happened is that [[]] is a one-element list containing an empty list,
so all three elements of [[]] * 3 are references to this single empty list.
Modifying any of the elements of lists modifies this single list. You can create a list of different lists this way:

>>> lists = [[] for i in range(3)]
>>> lists[0].append(3)
>>> lists[1].append(5)
>>> lists[2].append(7)
>>> lists
[[3], [5], [7]]

参考

延伸一下copy和deepcopy的问题。
举个例子,请问打印的aaa.a和aaa.a_b.b的值分别是多少?

class AAA():
    def __init__(self,a=0):
        self.a = a
        self.a_b = BBB()      
class BBB():
    def __init__(self,b=0):
        self.b = b
aaa = AAA(10)
bbb = aaa
bbb.a = 9
print(aaa.a)
bbb.a_b.b = 8
print(aaa.a_b.b)
#这里aaa.a应该是9,aaa.a_b.b应该是8

上面这个其实很好理解,就是bbb直接引用aaa,bbb中改变之后,aaa中也被改变了。
下面开始升级版,请问aaa.a和aaa.a_b.b的值是多少:

import copy
class AAA():
    def __init__(self,a=0):
        self.a = a
        self.a_b = BBB()      
class BBB():
    def __init__(self,b=0):
        self.b = b 
aaa = AAA(10)
bbb = copy.copy(aaa)
bbb.a = 9
print(aaa.a)
bbb.a_b.b = 8
print(aaa.a_b.b)
#这里aaa.a应该是10,aaa.a_b.b应该是8

其实copy通常叫做浅copy,也就是在赋值更改时,只对浅层的值进行复制(完全独立),对深层的值仍然是引用,bbb.a_b改变之后,aaa.a_b也会随着改变。
那么,现在下面的aaa.a和aaa.a_b.b的值又是多少呢?

import copy
class AAA():
    def __init__(self,a=0):
        self.a = a
        self.a_b = BBB()      
class BBB():
    def __init__(self,b=0):
        self.b = b 
aaa = AAA(10)
bbb = copy.deepcopy(aaa)
bbb.a = 9
print(aaa.a)
bbb.a_b.b = 8
print(aaa.a_b.b)
这里aaa.a应该是10,aaa.a_b.b应该是0

deepcopy才是真正意义上的完全复制,复制之后和原来的对象和值没有任何关系。
同时,嵌套的list,也存在同样的情况,不再赘述。

>>> import copy
>>> a = [1,2,3,[1,2,3]]
>>> b = copy.copy(a)
>>> b[0] = 10
>>> b[3][0] = 10
>>> a
[1, 2, 3, [10, 2, 3]]
>>> b = copy.deepcopy(a)
>>> b[0] = 10
>>> b[3][0] = 10
>>> b
[10, 2, 3, [10, 2, 3]]
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值