文章目录

  • 一. 数据类型
  • 1. 不可变数据类型
  • 2. 可变数据类型
  • 3. 赋值
  • 二. 深浅拷贝
  • 1. 浅拷贝
  • ① ==简单的==可变数据类型
  • ② ==复杂的==可变数据类型
  • ③ ==简单的==不可变数据类型
  • ④ ==复杂的==不可变数据类型
  • ⑤ 浅拷贝栗子
  • Ⅰ. 切片操作
  • Ⅱ. 工厂函数
  • Ⅲ. copy模块中的copy函数
  • 2. 深拷贝
  • ① ==简单的==可变数据类型
  • ② ==复杂的==可变数据类型
  • ③ ==简单的==不可变数据类型
  • ④ ==复杂的==不可变数据类型
  • 3. 深浅拷贝特殊案例
  • ① 可变嵌套不可变类型
  • ② ==不可变嵌套可变类型==
  • 4. 总结
  • ① 浅拷贝只能拷贝一层
  • ② 深拷贝能拷贝多层
  • ③ 可变类型拷贝可开辟新的内存空间
  • ④ 不可变类型拷贝对象的引用关系,不可开辟新的内存空间
  • ⑤ 特殊:不可变嵌套可变,深拷贝时,整体都可以进行完全拷贝
  • 一. 数据类型

  • 变量:是一个系统表的元素,拥有指向对象的连接空间
  • 对象:被分配的一块内存,存储其所代表的值
  • 引用:是自动形成的从变量到对象的指针
  • 类型:属于对象,而非变量
  • 1. 不可变数据类型

    一旦创建就不可修改的对象,包括数值类型、字符串、布尔类型、元组

    #定义一个变量a
    a = "python"
    
    print(id(a))
    

    b=10
    print(id(b))#140710918126944
    
    b="hello"
    print(id(b))#1629196172080
    

    2. 可变数据类型

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

    3. 赋值

    只是复制了新对象的引用,不会开辟新的内存空间

    a = 10
    b = a
    print(id(a))#140711658356064
    print(id(b))#140711658356064
    
    c = [1, 2, 3]
    d = c
    print(id(c))#1930836595208
    print(id(d))#1930836595208
    

    二. 深浅拷贝

    拷贝就是复制操作,其拷贝的值是相同的,但引用关系有所不同

    1. 浅拷贝

    浅拷贝,能力有限,只能拷贝最外层对象(只需要为外层开辟内存空间),无法拷贝内层对象

    简单的可变数据类型

    对于简单的可变数据类型,浅拷贝相当于把原对象的值进行拷贝,需要在内存中开辟一块新的内存空间

    import copy
    
    list1 = [1, 3, 5]
    list2 = copy.copy(list1)
    
    # 值-相同
    print(list1)  # [1, 3, 5]
    print(list2)  # [1, 3, 5]
    
    # 地址-不同
    print(id(list1))  # 1541605108232
    print(id(list2))  # 1541605108296
    

    复杂的可变数据类型

    对于复杂的可变数据类型,浅拷贝只能拷贝可变数据类型的最外层对象,而无法拷贝内层对象,所以只需要为最外层对象开辟内存空间,内层对象拷贝后的引用关系与原对象保持不变

    import copy
    
    list1 = [1, 3, 5,[7,9]]
    list2 = copy.copy(list1)
    
    # 值-相同
    print(list1)  # [1, 3, 5,[7,9]]
    print(list2)  # [1, 3, 5,[7,9]]
    
    # 地址-不同
    print(id(list1))  # 1541605108232
    print(id(list2))  # 1541605108296
    
    # 地址-相同
    print(id(list1[3]))  # 2850758572616
    print(id(list2[3]))  # 2850758572616
    

    简单的不可变数据类型

    对于简单的不可变数据类型,不可变数据类型地址一旦固定,值就无法改变了,又由于浅拷贝需要把自身的对象空间赋值给另外一个变量,为了保证数据一致,只能让其指向相同的内存空间(不需要额外开辟内存空间)

    import copy
    
    a = (1, 3, 5)
    b = copy.copy(a)
    
    # 值-相同
    print(a)  # (1, 3, 5)
    print(b)  # (1, 3, 5)
    
    # 地址-相同
    print(id(a))  # 2350406710360
    print(id(b))  # 2350406710360
    
    

    复杂的不可变数据类型

    对于复杂的不可变数据类型,浅拷贝只能拷贝变量的值,无法拷贝内存空间(无法开辟新的内存空间),无法拷贝内层对象

    import copy
    
    a = (1, 3, 5, (7, 9))
    b = copy.copy(a)
    
    # 值-相同
    print(a)  # (1, 3, 5, (7, 9))
    print(b)  # (1, 3, 5, (7, 9))
    
    # 地址-相同
    print(id(a))  # 2350406710360
    print(id(b))  # 2350406710360
    
    # 地址-相同
    print(id(a[3]))  # 2109112683592
    print(id(b[3]))  # 2109112683592
    


    无法拷贝内层对象

    import copy
    
    a = (1, 3, 5, (7, 9))
    b = copy.copy(a)
    
    # 值-相同
    print(a)  # (1, 3, 5, [7, 9]))
    print(b)  # (1, 3, 5, [7, 9])
    
    # 地址-相同
    print(id(a))  # 2350406710360
    print(id(b))  # 2350406710360
    
    # 地址-相同
    print(id(a[3]))  # 2109112683592
    print(id(b[3]))  # 2109112683592
    

    ⑤ 浅拷贝栗子

    Ⅰ. 切片操作
    lst = [1,2,[3,4]]
    切片操作:lst1 = lst[:] 或者 lst1 = [each for each in lst]
    

    [:]它与[0:]相似,意思是从0索引拆分到末尾。它返回一个新列表。

    Ⅱ. 工厂函数
    lst1 = list(lst)
    
    Ⅲ. copy模块中的copy函数
    lst1 = copy.copy(lst)
    

    但是在lst中有一个嵌套的list[3,4],如果我们修改了它,情况就不一样了。

    2. 深拷贝

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

    简单的可变数据类型

    对于简单的可变数据类型,深拷贝可以对对象进行完全拷贝,生成一块独立的内存空间,两个变量没有任何关系

    import copy
    
    a = [1, 3, 5]
    b = copy.deepcopy(a)
    
    # 值-相同
    print(a)  # [1, 3, 5]
    print(b)  # [1, 3, 5]
    
    # 地址-不相同
    print(id(a))  # 1763734399496
    print(id(b))  # 1763734399560
    

    复杂的可变数据类型

    对于复杂的可变数据类型,深拷贝可以对对象进行完全拷贝,不仅可以拷贝外层对象,也可以拷贝内层对象,而且完全独立

    import copy
    
    a = [1, 3, 5, [7, 9]]
    b = copy.deepcopy(a)
    
    # 值-相同
    print(a)  # [1, 3, 5, [7, 9]]
    print(b)  # [1, 3, 5, [7, 9]]
    
    # 地址-不相同
    print(id(a))  # 2891527236360
    print(id(b))  # 2891527236616
    
    # # 地址-不相同
    print(id(a[3]))  # 2891527236296
    print(id(b[3]))  # 2891527283912
    
    

    简单的不可变数据类型

    对于简单的不可变数据类型,深拷贝也只能拷贝对象的引用关系,所以看到的记过就是a和b只想了相同的内存空间

    import copy
    
    a = (1, 3, 5)
    b = copy.deepcopy(a)
    
    # 值-相同
    print(a)  # (1, 3, 5)
    print(b)  # (1, 3, 5)
    
    # 地址-相同
    print(id(a))  # 1719625069656
    print(id(b))  # 1719625069656
    

    复杂的不可变数据类型

    对于复杂的不可变数据类型,深拷贝也只能拷贝对象的引用关系,所以看到的记过就是a和b只想了相同的内存空间

    import copy
    
    a = (1, 3, 5, (7, 9))
    b = copy.deepcopy(a)
    
    # 值-相同
    print(a)  # (1, 3, 5, (7, 9))
    print(b)  # (1, 3, 5, (7, 9))
    
    # 地址-相同
    print(id(a))  # 1928373693320
    print(id(b))  # 1928373693320
    
    # 地址-相同
    print(id(a[3]))  # 1928373701640
    print(id(b[3]))  # 1928373701640
    

    3. 深浅拷贝特殊案例

    ① 可变嵌套不可变类型

    外层是可变类型,多以可以进行完全拷贝(需生成内存空间),但内层对象是不可变数据类型,所以只能拷贝引用关系

    import copy
    
    a = [1, 3, 5, (7, 9)]
    b = copy.copy(a)
    c = copy.deepcopy(a)
    
    # 值-相同
    print(a)  # [1, 3, 5, (7, 9)]
    print(b)  # [1, 3, 5, (7, 9)]
    print(c)  # [1, 3, 5, (7, 9)]
    
    # 地址-不同
    print(id(a))  # 2197686397896
    print(id(b))  # 2197686397960
    print(id(c))  # 2197686398216
    
    # 地址-相同
    print(id(a[3]))  # 2197686094920
    print(id(b[3]))  # 2197686094920
    print(id(c[3]))  # 2197686094920
    
    

    不可变嵌套可变类型

    浅拷贝结论与之前结论一致,都只能拷贝引用关系
    深拷贝,有点不同,如果这种类型使用深拷贝,其整体都可以进行完全拷贝

    import copy
    
    a = (1, 3, 5, [7, 9])
    b = copy.copy(a)
    c = copy.deepcopy(a)
    
    # 值-相同
    print(a)#(1, 3, 5, [7, 9])
    print(b)#(1, 3, 5, [7, 9])
    print(c)#(1, 3, 5, [7, 9])
    
    #地址ab同,与c不同
    print(id(a))#2983608461896
    print(id(b))#2983608461896
    print(id(c))#
    
    #地址ab同,与c不同
    print(id(a[3]))#2983608498888
    print(id(b[3]))#2983608498888
    print(id(c[3]))#2983608499144
    
    

    浅拷贝

    深拷贝

    4. 总结

    ① 浅拷贝只能拷贝一层

    ② 深拷贝能拷贝多层

    ③ 可变类型拷贝可开辟新的内存空间

    ④ 不可变类型拷贝对象的引用关系,不可开辟新的内存空间

    ⑤ 特殊:不可变嵌套可变,深拷贝时,整体都可以进行完全拷贝

    作者:赛丽曼

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中的深浅拷贝

    发表回复