zoukankan      html  css  js  c++  java
  • Python中的赋值(复制)、浅拷贝与深拷贝

    https://zhuanlan.zhihu.com/p/54011712

    首先需要了解下几个概念

     

    • 变量:是一个系统表的元素,拥有指向对象的连接空间
    • 对象:被分配的一块内存,存储其所代表的值
    • 引用:是自动形成的从变量到对象的指针
    • 类型:属于对象,而非变量
    • 不可变对象:一旦创建就不可修改的对象,包括字符串、元组、数值类型

    (该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。)

    • 可变对象:可以修改的对象,包括列表、字典、集合

    (该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上是其所指的值直接发生改变,并没有发生复制行为,也没有开辟新的地址,通俗点说就是原地改变。)

    当我们写:

    a = 'python'

    Python解释器干的事情:

    1. 创建也变量a

    2. 创建一个对象(分配一块内存),来存储值 'python'

    3. 将变量与对象,通过指针连接起来,从变量到对象的连接称之为引用(变量引用对象)


     

    1.赋值: 只是复制了新对象的引用,不会开辟新的内存空间。

    并不会产生一个独立的对象单独存在,只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。

     

    2.浅拷贝: 创建新对象,其内容是原对象的引用。

    浅拷贝有三种形式: 切片操作,工厂函数,copy模块中的copy函数。

    如: lst = [1,2,[3,4]]

    切片操作:lst1 = lst[:] 或者 lst1 = [each for each in lst]

    工厂函数:lst1 = list(lst)

    copy函数:lst1 = copy.copy(lst)

    浅拷贝之所以称为浅拷贝,是它仅仅只拷贝了一层,拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已,在lst中有一个嵌套的list[3,4],如果我们修改了它,情况就不一样了。

    浅复制要分两种情况进行讨论:

    1)当浅复制的值是不可变对象(字符串、元组、数值类型)时和“赋值”的情况一样,对象的id值(id()函数用于获取对象的内存地址)与浅复制原来的值相同。

    2)当浅复制的值是可变对象(列表、字典、集合)时会产生一个“不是那么独立的对象”存在。有两种情况:

    第一种情况:复制的对象中无复杂子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

    第二种情况:复制的对象中有复杂子对象(例如列表中的一个子元素是一个列表),如果不改变其中复杂子对象,浅复制的值改变并不会影响原来的值。 但是改变原来的值中的复杂子对象的值会影响浅复制的值。

     

    3.深拷贝:和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。

    所以改变原有被复制对象不会对已经复制出来的新对象产生影响。

    只有一种形式,copy模块中的deepcopy函数

    对于不可变对象的深浅拷贝

    import copy
    a=(1,2,3)
    
    print("=====赋值=====")
    b=a
    print(a)
    print(b)
    print(id(a))
    print(id(b))
    
    print("=====浅拷贝=====")
    b=copy.copy(a)
    print(a)
    print(b)
    print(id(a))
    print(id(b))
    
    print("=====深拷贝=====")
    b=copy.deepcopy(a)
    print(a)
    print(b)
    print(id(a))
    print(id(b))

    结果:

    =====赋值=====
    (1, 2, 3)
    (1, 2, 3)
    43481128
    43481128
    =====浅拷贝=====
    (1, 2, 3)
    (1, 2, 3)
    43481128
    43481128
    =====深拷贝=====
    (1, 2, 3)
    (1, 2, 3)
    43481128
    43481128

    不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。

    一句话就是,不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。

     

    对于可变对象深浅拷贝

    import copy
    a=[1,2,3]
    
    print("=====赋值=====")
    b=a
    print(a)
    print(b)
    print(id(a))
    print(id(b))
    
    print("=====浅拷贝=====")
    b=copy.copy(a)
    print(a)
    print(b)
    print(id(a))
    print(id(b))
    
    print("=====深拷贝=====")
    b=copy.deepcopy(a)
    print(a)
    print(b)
    print(id(a))
    print(id(b))

    结果:

    =====赋值=====
    [1, 2, 3]
    [1, 2, 3]
    37235144
    37235144
    =====浅拷贝=====
    [1, 2, 3]
    [1, 2, 3]
    37235144
    37191432
    =====深拷贝=====
    [1, 2, 3]
    [1, 2, 3]
    37235144
    37210184

    赋值: 值相等,地址相等

    copy浅拷贝:值相等,地址不相等

    deepcopy深拷贝:值相等,地址不相等

     

    对于可变对象深浅拷贝(外层改变元素)

    import copy
    l=[1,2,3,[4, 5]]
    
    l1=l #赋值
    l2=copy.copy(l) #浅拷贝
    l3=copy.deepcopy(l) #深拷贝
    l.append(6)
    
    print(l)  
    print(l1)
    print(l2)
    print(l3)

    结果:

    [1, 2, 3, [4, 5], 6]     #l添加一个元素6
    [1, 2, 3, [4, 5], 6]     #l1跟着添加一个元素6
    [1, 2, 3, [4, 5]]        #l2保持不变
    [1, 2, 3, [4, 5]]        #l3保持不变

     

     

    对于可变对象深浅拷贝(内层改变元素)

    import copy
    l=[1,2,3,[4, 5]]
    
    l1=l #赋值
    l2=copy.copy(l) #浅拷贝
    l3=copy.deepcopy(l) #深拷贝
    l[3].append(6) 
    
    print(l) 
    print(l1)
    print(l2)
    print(l3)

    结果:

    [1, 2, 3, [4, 5, 6]]      #l[3]添加一个元素6
    [1, 2, 3, [4, 5, 6]]      #l1跟着添加一个元素6
    [1, 2, 3, [4, 5, 6]]      #l2跟着添加一个元素6
    [1, 2, 3, [4, 5]]         #l3保持不变

    1.外层添加元素时,浅拷贝不会随原列表变化而变化;内层添加元素时,浅拷贝才会变化。
    2.无论原列表如何变化,深拷贝都保持不变。
    3.赋值对象随着原列表一起变化。

  • 相关阅读:
    myEclipse环境下配置springMvc项目,进行简单的请求
    自记录:git如何上传文档到git@osc
    java UDP网路编程
    Dom解析xml源代码
    SAX解析XML文件实例代码
    javaFile循环列出指定目录下的所有文件(源代码)
    javaIO流实现读写txt文件
    Java类之间的关联关系(转载)
    Python基本语法
    Python3.4入门之ifelse错误解决方案
  • 原文地址:https://www.cnblogs.com/zy09/p/11855706.html
Copyright © 2011-2022 走看看