Python3列表浅拷贝在多层数据结构中的运用

  • 背景
  • 问题
  • 思考
  • 结论
  • 背景

    在使用Python3做洛谷B2108题的过程中,需要将原始数据进行模糊化(见题目)处理后更新二维数组,那么就涉及到一个问题:如果在原数组中修改,将影响到后续数据的运算结果,于是对原始二维数组进行了浅拷贝,创建了一个新的二维数组,将原始二维数组用于提取原始数据,运算后的结果写入新的二维数组。但是经过尝试,发现一旦新数组中底层的元素被改动,原始数组也将收到影响。

    matrix = [
        [100, 0, 100, 0, 50],
        [50, 100, 200, 0, 0],
        [50, 50, 100, 100, 200],
        [100, 100, 50, 50, 100],
    ]
    
    temp_matrix = matrix.copy()
    [print(i) for i in matrix]
    print()
    [print(i) for i in temp_matrix]
    

    执行以上代码,输出结果为:

    
    [100, 0, 100, 0, 50]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]
    
    [100, 0, 100, 0, 50]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]

    对temp_matrix中的元素进行修改之后再进行输出:

    temp_matrix[0][0] = matrix[1][2]
    
    [print(i) for i in matrix]
    print()
    [print(i) for i in temp_matrix]

    执行以上代码,输出结果为:

    [0, 0, 100, 0, 50]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]
    
    [0, 0, 100, 0, 50]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]

    可见两个二维数组虽然看起来是不同的对象,但是在对其中一个进行修改的同时,另一个也将受到影响。

    问题

    第二个二维数组是第一个二维数组浅拷贝而来,通过id()方法查看两个对象的内存地址也不相同,为何仍会互相影响?

    print(id(matrix))
    print(id(temp_matrix))

    执行以上代码,输出结果为:

    2509216600384
    2509216600448

    思考

    经过反复测试,不论是直接对二维数组进行浅拷贝,还是遍历二维数组后逐个添加进新的二维数组,之后在对新二维数组中的数字进行改动的时候,都会影响原始二维数组中的数据。

    temp_matrix = []
    for i in matrix:
        temp_matrix.append(i)
    
    temp_matrix[0][0] = matrix[1][2]
    
    [print(i) for i in matrix]
    print()
    [print(i) for i in temp_matrix]

    执行以上代码后结果仍然相同,两个二维数组中的数据都发生了改变。

    但是

    如果将二维数组中嵌套的一维数组作为一个整体进行改动,则不会影响原始数据:

    temp_matrix[0] = matrix[1]
    
    [print(i) for i in matrix]
    print()
    [print(i) for i in temp_matrix]

    执行以上代码,输出结果为:

    [100, 0, 100, 0, 50]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]
    
    [50, 100, 200, 0, 0]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]

    这是因为当原对象存在多层嵌套的情况下,浅拷贝copy()只拷贝了调用这个方法的这一层的数据结构,这一层所包含的数据变化时,是不会相互影响的,但是当原数据对象内部嵌套数据中的数据发生变化后,相应的浅拷贝后的对象也会发生变化。

    在上面的例子中,temp_matrix是对matrix的浅拷贝,指的是在这两个列表中的元素互不影响,但是由于这两个列表中的元素还存在内部结构(也都是列表),故而浅拷贝的互不影响原则不会作用于深层的数据,所以发生了某种“量子纠缠”效应。

    这就像是一所学校,按照同样的蓝图建设了许多教室,里面有相同的墙体,窗户,门,桌椅,黑板,喇叭,其中某一间教室因为喇叭坏了,换了一个新型号,这一事件不影响其他的教室;但是当广播室更换播放的音乐的时候,所有教室的喇叭发出的声音都会改变。

    结论

    要想使两个二维数组甚至更多层次的数据结构中的数据完全不关联,应该使用以下方法:

    temp_matrix = []
    for i in matrix:
        temp_matrix.append(i.copy())
    
    temp_matrix[0][0] = matrix[1][2]
    
    [print(i) for i in matrix]
    print()
    [print(i) for i in temp_matrix]

    执行以上代码,输出结果为:

    [100, 0, 100, 0, 50]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]
    
    [200, 0, 100, 0, 50]
    [50, 100, 200, 0, 0]
    [50, 50, 100, 100, 200]
    [100, 100, 50, 50, 100]

    可见,此方法,在最底层的数据结构中进行了浅拷贝,从根本上将两个数据完全隔绝开,回到题目中,可以实现从原始二维数组中提取数据,进行计算后改写新的二维数组:

    # 获取输入
    temp = input().split()
    n = int(temp[0])
    m = int(temp[1])
    
    # 构造原始二维数组
    matrix = [list(map(int,input().split())) for _ in range(n)]
    
    # 构造新的二维数组
    temp_matrix = [i.copy() for i in matrix]
    
    # 遍历行
    for row in range(1,n-1):
        # 遍历列
        for col in range(1,m-1):
            # 从原始数组中取值,写入新数组
            temp_matrix[row][col] = round((matrix[row-1][col] + matrix[row+1][col] + matrix[row][col-1] + matrix[row][col+1] + matrix[row][col])/5)
    
    # 输出
    [print(i) for i in temp_matrix]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值