zoukankan      html  css  js  c++  java
  • python中的深拷贝和浅拷贝理解

    在python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。以下分两个思路来分别理解浅拷贝和深拷贝:

    • 利用切片操作和工厂方法list方法拷贝
    • 利用copy中的deepcopy方法进行拷贝

    1、利用切片操作和工厂方法list方法拷贝

    代码场景:有一个小伙jack,tom通过切片操作拷贝jack,anny通过工厂方法拷贝jack。

    >>> jack = ['jack', ['age', 20]]
    >>> tom = jack[:]
    >>> anny = list(jack)

    来看下三者的id值:

    >>> print id(jack), id(tom), id(anny)
    144846988 144977164 144977388

    从id值来看,三者是不同的对象。为tom和anny重新命名为各自的名称:

    >>> tom[0] = 'tom'
    >>> anny[0] = 'anny'
    >>> print jack, tom, anny
    ['jack', ['age', 20]] ['tom', ['age', 20]] ['anny', ['age', 20]]

    从这里来看一切正常,可是anny只有18岁,重新为anny定义岁数。

    >>> anny[1][1] = 18
    >>> print jack, tom, anny
    ['jack', ['age', 18]] ['tom', ['age', 18]] ['anny', ['age', 18]]

    这时候奇怪的事情发生了,jack、tom、anny的岁数都发生了改变,都变成了18了。jack、tom、anny他们应当都是不同的对象,怎么会互相影响呢?看下jack,tom,anny的内部元素每个元素id:

    >>> [id(x) for x in jack]
    [3073896320L, 3073777580L]
    >>> [id(x) for x in tom]
    [144870744, 3073777580L]
    >>> [id(x) for x in anny]
    [144977344, 3073777580L]

    恍然大悟,原来jack、tom、anny的岁数元素指向的是同一个元素。修改了其中一个,当然影响其他人了。那为什么修改名称没影响呢?原来在python中字符串不可以修改,所以在为tom和anny重新命名的时候,会重新创建一个’tom’和’anny’对象,替换旧的’jack’对象。为了便于理解,我画了一个草图:

    python浅拷贝图解

    python浅拷贝图解

    2、利用copy中的deepcopy方法进行拷贝

    为了让他们之间不互相影响,用deepcopy来试试

    >>> jack = ['jack', ['age', '20']]
    >>> import copy
    >>> tom = copy.deepcopy(jack)
    >>> anny = copy.deepcopy(jack)

    根据第一个思路进行重命名,重定岁数操作:

    >>> tom[0] = 'tom'
    >>> anny[0] = 'anny'
    >>> print jack, tom, anny
    ['jack', ['age', '20']] ['tom', ['age', '20']] ['anny', ['age', '20']]
    >>> anny[1][1] = 18
    >>> print jack, tom, anny
    ['jack', ['age', '20']] ['tom', ['age', '20']] ['anny', ['age', 18]]

    这时候他们之间就不会互相影响了。打印出每个人的内部元素每个id:

    >>> [id(x) for x in jack]
    [139132064, 3073507244L]
    >>> [id(x) for x in tom]
    [139137464, 139132204]
    >>> [id(x) for x in anny]
    [139141632, 139157548]

    他们的内部元素也都指向了不同的对象。

    小结:

    思路一:利用切片操作和工厂方法list方法拷贝就叫浅拷贝,只是拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。

    思路二:利用copy中的deepcopy方法进行拷贝就叫做深拷贝,外围和内部元素都进行了拷贝对象本身,而不是引用。

    但是对于数字,字符串和其他原子类型对象等,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。

  • 相关阅读:
    Linux之文件处理命令
    Linux基础命令
    rip实验
    Linux基础之磁盘分区
    mysql安装
    centos Apache、php、mysql默认安装路径
    You probably tried to upload too large file. Please refer to documentation for ways to workaround this limit.
    Wrong permissions on configuration file, should not be world writable!
    机器会学习么 学习总结
    实验 5 Spark SQL 编程初级实践
  • 原文地址:https://www.cnblogs.com/conanwang/p/5968374.html
Copyright © 2011-2022 走看看