浅拷贝问题浅析与解决方法(基于python3.4)


用markdown写的第一篇技术博客,使用Python类复制时走过的坑,


1 问题描述

  • 浅拷贝问题最简单的体现方式,将一个类a(list等)赋值给另一个变量b,则修改a,会同时改变b。
    ‘’’
    》 a
    [1, 2, 1]
    》 b=a
    》a
    [1, 2, 1]
    》 b
    [1, 2, 1]
    》 a.append(3)
    》 a
    [1, 2, 1, 3]
    》 b
    [1, 2, 1, 3]

    ‘’’
  • 以如下方式复制扩展的列表,也存在浅拷贝问题,c中的三个list元素指向了同一个list原型,对其中一个元素进行扩展时 ,三个元素同时发生了变化。
    ‘’’
    》c=[[]]*3
    》 c
    [[], [], []]
    》 c[1].append(1)
    》 c
    [[1], [1], [1]]
    》 ‘’’
  • 下面这段代码更让人吃惊,将c[1]赋值给b,修改b时,c的元素也全部发生了变化。
    ‘’’
    》 c=[[]]*3
    》 c
    [[], [], []]
    》 b=c[1]
    》 b
    []
    》b.append(1)
    》 b
    [1]
    》 c
    [[1], [1], [1]]
    ‘’’
  • 对c中的元素进行加减乘除的运算修改时,c中的其他元素也同时变化,基本可以表明用c = [[]]*3这种方式产生的c中的三个元素,本质上是同一个元素,
    ‘’’
    》c[1][0]
    1
    》 c[1][0] += 1
    》 c[1][0] += 1
    》 c[1][0]
    3
    》 c
    [[3], [3], [3]]
    ‘’’

2.浅拷贝的解决方案

  • 解决上述浅拷贝问题,可利用copy模块的copy()和deepcopy()方法。 Import copy 或 from copy import deepcopy 经过测试(python3.4)主要特点如下:

1、list类进行copy时,两个变量相互独立,互不影响。
‘’’
》 a=[1,2,3]
》 b=a.copy()
》 b
[1, 2, 3]
》 b[2] =8
》 a
[1, 2, 3]
》 b
[1, 2, 8]
》 b.append(2)
》 b
[1, 2, 8, 2]
》 a
[1, 2, 3]
‘’’

2、dict类存在浅拷贝问题,替换新复制的字典里的值不会改变原字典,但修改一个值时,会影响到原字典。额。。这个很绕。因此需要特别注意对值进行替换(全部)和修改(部分)的差别。
deepcopy—dict

3.使用deepcopy(var)可以完全的复制一个类,两个类不再有任何关联,从而解决浅拷贝问题。

4、对于自定义类,由于没有内建的copy()函数,需要采用deepcopy进行完全复制。要注意:copy属于python自带类(list,dict等)内建的方法,采用dict.copy()调用,而deepcopy属于导入的外部函数,采用参数的形式,deepcopy(var)对变量进行复制

3.总结

  • 涉及到类的复制和赋值时,最好不好直接用class1 = class2的方式对类进行赋值,也不要采用[class]*number 的方式,对类进行拓展。直接采用deepcopy()方法,就能避免浅拷贝问题。

最后编辑时间为: Jan.14, 2018 at 21:16


打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

Powered by shousunny,分享从这里开始,精彩与您同在






Valine - A simple comment system based on Leancloud.