zoukankan      html  css  js  c++  java
  • 深浅拷贝

    涉及到深浅拷贝,我们先不解释这个问题,先来看一下复制的问题,这里的复制不再是简单的字符串之间的复制,而是列表之间的复制

    好,首先提出一个需求:将一个列表复制一份,且要求复制与被复制之间的修改不能相互影响,一个很简单的实现:

    names_class1=['张三','李四','王五','赵六']
    names_class1_copy=['张三','李四','王五','赵六']

    但这时候问题来了,如果列表内容很多呢?再这样机械的复制就太naive了,有人就这样实现:

    names_class1=['张三','李四','王五','赵六']
    names_class1_copy=names_class1

    这里可以实现复制,但无法满足复制与被复制之间的修改不能相互影响

    这样只是一个简单的类似于一个起别名的操作,两个变量共享一个内存,你改我也改,并不是一个真正的复制

    于是就需要用到一个方法来处理叫大数据量的复制,列表里为我们内置了copy方法:

    names_class1=['张三','李四','王五','赵六',[1,2,3]]
    names_class1_copy=names_class1.copy()
    
    names_class1_copy[0]='zhangsan'
    print(names_class1)
    print(names_class1_copy)
    '''
    ['张三', '李四', '王五', '赵六', [1, 2, 3]]
    ['zhangsan', '李四', '王五', '赵六', [1, 2, 3]]
    
    我们可以看到对复制来的进行的修改不会导致被复制列表的修改
    ''' 
    # 见证奇迹的发生
    names_class1_copy[4][2]=5
    print(names_class1)
    print(names_class1_copy)
    '''运行时记得注释前面的修改
    ['张三', '李四', '王五', '赵六', [1, 2, 5]]
    ['张三', '李四', '王五', '赵六', [1, 2, 5]]
    ''' 

    当我们对  names_class1_copy[0]  进行修改时,可以看到不会对  names_class1[0]   产生修改,但当我们对    names_class1_copy[4][2]    进行修改时,可以看到     names_class1[4][2]    也发生了变化。

    这里就涉及到我们的深浅拷贝的问题了

    为简单起见,我们重新写一段代码演示:

    s1 = [[1,2], 3, 4]
    s2 = s1.copy()
    
    print("id:s1",id(s1))
    print("id:s2",id(s2))
    
    print("id:s1[0],s1[1],s1[2]",id(s1[0]),id(s1[1]),id(s1[2]))
    print("id:s2[0],s2[1],s2[2]",id(s2[0]),id(s2[1]),id(s2[2]))
    
    print("id:s1[0][0],s1[0][1]",id(s1[0][0]),id(s1[0][1]))
    print("id:s2[0][0],s2[0][1]",id(s2[0][0]),id(s2[0][1]))
    
    
    '''结果
    id:s1 1508552982856
    id:s2 1508552984072
    id:s1[0],s1[1],s1[2] 1508552956936 1440116256 1440116288
    id:s2[0],s2[1],s2[2] 1508552956936 1440116256 1440116288
    id:s1[0][0],s1[0][1] 1440116192 1440116224
    id:s2[0][0],s2[0][1] 1440116192 1440116224
    '''

    先是输出一下各内容的地址,用图表示一下,这里可以看出copy()方法实现的是第一层的copy,也就是图中黄色箭头的部分

    继续我们的代码,这次我们对内容进行修改:

    s2[1] = 'pp'
    
    print(s1)
    print(s2)
    
    print("id:s1[1]",id(s1[1]))
    print("id:s2[1]",id(s2[1]))
    
    print("id:s1[2]",id(s1[2]))
    print("id:s2[2]",id(s2[2]))
    
    '''结果
    [[1, 2], 3, 4]
    [[1, 2], 'pp', 4]
    id:s1[1] 1440116256
    id:s2[1] 2112166200240
    id:s1[2] 1440116288
    id:s2[2] 1440116288
    '''

     这里的修改是将s2[1]的内容进行修改,可以看到并不会修改s1[1]的内容,这里也用图来说明一下:

    继续我们的代码,这次我们对列表中的列表内容进行修改:

    s2[0][1] = 'pl'
    
    print(s1)
    print(s2)
    
    print("id:s1[0][0],s1[0][1]",id(s1[0][0]),id(s1[0][1]))
    print("id:s2[0][0],s2[0][1]",id(s2[0][0]),id(s2[0][1]))
    
    '''结果:
    [[1, 'pl'], 3, 4]
    [[1, 'pl'], 'pp', 4]
    id:s1[0][0],s1[0][1] 1440116192 1942456009536
    id:s2[0][0],s2[0][1] 1440116192 1942456009536
    '''

     这次对s2的修改也造成了s1内容的变化,继续用一张图来说明一下:

     这里就是浅拷贝的秘密所在,因为我们前面说了是第一层拷贝,这里我们的第二层指针,相当于共享的,也就是别名。于是任何地方的修改都会导致其他地方的变化

  • 相关阅读:
    组件
    Django
    面向对象
    异常处理
    模块1
    Java中权限设置
    java反射机制
    JavaScript提高篇之面向对象之单利模式工厂模型构造函数原型链模式
    JavaScript提高篇之预解释作用域以及this原理及其应用
    js-引用类型-Array
  • 原文地址:https://www.cnblogs.com/panlei3707/p/8398373.html
Copyright © 2011-2022 走看看