zoukankan      html  css  js  c++  java
  • python 深复制和浅复制详解

    python 深复制和浅复制详解

    觉得有用的话,欢迎一起讨论相互学习~


    我的微博我的github我的B站

    参考文献
    莫烦老师
    博文

    id(x)函数

    • id()函数可以查看一个变量在内存中的地址

    变量赋值给变量-拷贝引用

    对于以下代码

    >>> import copy
    >>> a=[1,2,3]
    >>> b=a
    >>> id(a)
    """
    4382960392
    """
    >>> id(b)
    """
    4382960392
    """
    >>> id(a)==id(b)    #附值后,两者的id相同,为true。
    True
    >>> b[0]=222222  #此时,改变b的第一个值,也会导致a值改变。
    >>> print(a,b)
    [222222, 2, 3] [222222, 2, 3] #a,b值同时改变
    
    • 此时会发现,对于b=a这条命令而言,b是a的拷贝,指向的是内存中同一块地址即id(a)==id(b)通过改变b的元素也可以起到改变a中元素的作用,同理,改变a中的元素也会改变b中的元素。

    可变对象与不可变对象

    • 可变对象是指,一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值; 值和地址不对应(列表)

    • 不可变对象是指,一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了 值和地址相互对应(int,float,complex,long,str,unicode,tuple)元组 tuple就属于不可变对象

    基本可变对象的深复制和浅复制

    • 基本可变对象不仅仅只有列表,还有字典等,这里使用列表举个简单的例子。
    a_list = [1, 2, 3]
    a_shallow_list = copy.copy(a_list)
    a_deep_list = copy.deepcopy(a_list)
    print("id of a_list", id(a_list), "id of a_shallow_list", id(a_shallow_list), "a_deep_list", id(a_deep_list))
    # id of a_list 2249250705672 id of a_shallow_list 2249201900552 a_deep_list 2249201900424
    
    • 其均会指向一个新的地址,即a_list,a_shallow_list,a_deep_list相互之间不影响。
    • 但是其中的元素是int类型,是不可变对象,因此其只要其中数值不变地址也不会变化。
    print("id of a_list[0]", id(a_list[0]), "id of a_shallow_list[0]", id(a_shallow_list[0]), "a_deep_list[0]", id(a_deep_list[0]))
    # id of a_list[0] 1887096560 id of a_shallow_list[0] 1887096560 a_deep_list[0] 1887096560
    # 基本可变对象中不可变对象的地址不会改变
    

    基本不可变对象的深复制和浅复制

    • 元组 tuple是不可变对象,只要地址改变其中的值也会改变,因此 深复制和浅复制 都不会改变其中元素的地址。
    a_tuple = (1, 2, 3)
    a_shallow_tuple = copy.copy(a_tuple)
    a_deep_tuple = copy.deepcopy(a_tuple)
    # 比较基本不可变对象,深复制和浅复制区别
    print("id of a_tuple", id(a_tuple), "a_shallow_tuple", id(a_shallow_tuple), "a_deep_tuple", id(a_deep_tuple))
    print("id of a_tuple[0]", id(a_tuple[0]), "a_shallow_tuple[0]", id(a_shallow_tuple[0]), "a_deep_tuple[0]",
          id(a_deep_tuple[0]))
    # id of a_tuple 2344837083280 a_shallow_tuple 2344837083280 a_deep_tuple 2344837083280
    # id of a_tuple[0] 1885130480 a_shallow_tuple[0] 1885130480 a_deep_tuple[0] 1885130480
    

    嵌套不可变对象的深复制和浅复制

    • 但是对于嵌套对象,只要其中包含 可以引用的可变对象深复制就会重新分配内存创建新的对象 。由于外层是元组对象,是不可变对象,浅复制则不会重新分配内存。 这里是 深复制和浅复制的区别之一而这里浅复制不改变地址的操作,也就表示操纵浅复制的对象也可以对原始对象进行操作。
    a1_tuple = (1, 2, (1, 2, 3), [1, 2, 3])
    a1_shallow_tuple = copy.copy(a1_tuple)
    a1_deep_tuple = copy.deepcopy(a1_tuple)
    
    # 复合嵌套不可变元素的深复制和浅复制区别
    print("id of a1_tuple", id(a1_tuple), "a1_shallow_tuple", id(a1_shallow_tuple), "a1_deep_tuple", id(a1_deep_tuple))
    print("id of a1_tuple[3]", id(a1_tuple[3]), "a1_shallow_tuple[3]", id(a1_shallow_tuple[3]), "a1_deep_tuple[3]",
          id(a1_deep_tuple[3]))
    
    # id of a1_tuple 2498218636296 a1_shallow_tuple 2498218636296 a1_deep_tuple 2498218638776
    # id of a1_tuple[3] 2498267415048 a1_shallow_tuple[3] 2498267415048 a1_deep_tuple[3] 2498218716040
    

    嵌套可变对象的深复制和浅复制

    • 这是常见的一种模式,也是网上博文最多讨论的一种模式,即外层是一个可变对象例如list,内层中也包含有可变对象list。
    • 浅复制会对外层可变对象进行复制,但是对内层可变对象不会复制,也就是说内层可变对象的地址不会改变。 这时改变拷贝对象的内层元素,原有对象内层对象也会改变。
    • 但是深复制不会有这种担忧,里里外外都是重新从内存中申请的空间,都是一个全新的对象。
    • 可以认为对于嵌套类型结构,深复制都是重新分配空间,建立的原来完全不同的对象。
    • 建议平时用深复制,不易出错~!
    a1_list = [1, 2, (1, 2, 3), [1, 2, 3]]
    a1_shallow_list = copy.copy(a1_list)
    a1_deep_list = copy.deepcopy(a1_list)
    # 复合嵌套可变元素的深复制和浅复制区别
    print("id of a1_list", id(a1_list), "id of a1_shallow_list", id(a1_shallow_list), "a1_deep_list", id(a1_deep_list))
    print("id of a1_list[3]", id(a1_list[3]), "id of a1_shallow_list[3]", id(a1_shallow_list[3]), "a1_deep_list[3]",
          id(a1_deep_list[3]))
    # id of a1_list 1453555407752 id of a1_shallow_list 1453555447432 a1_deep_list 1453555477384
    # id of a1_list[3] 1453604277640 id of a1_shallow_list[3] 1453604277640 a1_deep_list[3] 1453555448968
    
  • 相关阅读:
    为什么 ObjectiveC 很难
    PHP开发Windows桌面应用程序实例
    windows下借助InstantRails环境搭建redmine
    php,python,ruby,perl的优缺点?
    Ruby在windows上的eclipse开发环境搭建
    Python的web框架很多,比如Django,webpy等,但是哪一种综合实力最强呢?
    使用JRockit作为Eclipse的Java VM
    Fat Jar Eclipse PlugIn Tutorial
    ECLIPSE插件集合
    Java反编译利器Jad, Jode, Java Decompiler等及其IDE插件
  • 原文地址:https://www.cnblogs.com/cloud-ken/p/12638393.html
Copyright © 2011-2022 走看看