首页 > 其他分享 >深浅拷贝

深浅拷贝

时间:2024-01-13 23:25:06浏览次数:33  
标签:对象 list1 list 深浅 拷贝 copy original

【一】深浅拷贝问题的引入

  • 无论是深拷贝还是浅拷贝都是用来复制对象用的

  • 如果是浅拷贝,只会复制一层,如果拷贝的对象是可变数据类型,修改可变数据类型还会影响拷贝的对象

  • 在python中,深拷贝和浅拷贝是用于复制对象不同的两种方式

    list_original = [1, 2, 3, [4, 5, 6, ]]
    list_copy = list_original
    print(list_copy is list_original)
    # True
    
  • 通过将list_copy赋值为list_original,实际上是将list_copylist_original指向相同的内存地址。

  • 所以list_copy is list_original的结果为True,表示它们是同一个对象的两个引用。

  • 因此对list_copylist_original的修改都会影响到另一个。

【1】浅拷贝

  • 浅拷贝仅复制对象的一层内容,如果对象中包含了可变数据类型,拷贝的对象将与原对象共享内存地址

  • 这意味这两方任意一方发生改变时,另一方都会都到影响

    import copy
    
    original_list = [1, 2, 3, [1, 2]]
    # 使用浅拷贝创建拷贝对象
    cope_list = copy.copy(original_list)
    original_list[3].append(4)
    print(original_list)  # [1, 2, 3, [1, 2, 4]]
    print(cope_list)  # [1, 2, 3, [1, 2, 4]]
    
    print(cope_list is original_list) # False
    
    
  • 可以发现当我修改了原函数之后

  • 拷贝的内容也随之修改了

  • 但是两者指向不同的内存地址

(2)深拷贝

  • 深拷贝会创建一个完全独立的新对象,包括所有的嵌套对象。
  • 无论原对象的数据类型是可变还是不可变,深拷贝都会创建出新的对象,以后对原对象的修改不会影响到拷贝对象。
  • 以下是一个使用深拷贝的案例:
import copy

# 原对象
original_list = [1, 2, [3, 4]]
# 使用深拷贝创建拷贝对象
copied_list = copy.deepcopy(original_list)

# 修改原对象中的可变数据类型
original_list[2].append(5)

print("原对象:", original_list)
print("拷贝对象:", copied_list)
  • 可以看到,尽管修改了原对象中的可变数据类型,但拷贝对象保持不变。
  • 这是因为深拷贝创建了一个原对象完全独立的新对象,包括了所有嵌套对象的复制。
from copy import deepcopy

list_original = [1, 2, 3, [4, 5, 6, ]]
list_deep_copy = deepcopy(list_original)
list_deep_copy[3][1] = 888
print(list_original)
# [1, 2, 3, [4, 5, 6]]
print(list_deep_copy)
# [1, 2, 3, [4, 888, 6]]
  • 通过使用deepcopy()函数进行深拷贝,会递归地复制嵌套对象,包括嵌套列表。
  • 这意味着在深拷贝操作中不仅会创建一个新的顶层列表对象list_deep_copy,还会创建一个新的嵌套列表对象,并且其值与原始列表中的值相同。
  • 因此在对list_deep_copy中的嵌套列表进行修改时,并不会影响到原始的列表list_original,它们指向不同的内存地址。

(3)小结

  • 综上所述
    • 浅拷贝只复制顶层对象
    • 而深拷贝会递归复制整个对象结构。
  • 在涉及到可变对象嵌套的情况下
    • 深拷贝是一种更安全的选项
    • 因为它可以确保对新对象的修改不会影响原始对象。

【二】深浅拷贝问题详解

  • 深拷贝和浅拷贝是常用的操作,它们在处理对象和数据结构时非常有用。
  • 让我们详细解释深拷贝和浅拷贝的概念,并结合案例进行演示。

(1)深拷贝:

  • 深拷贝是指创建一个新的对象,该对象与原始对象完全独立。
  • 换句话说,它会递归地复制所有嵌套对象,包括它们的内容,以便我们在修改新对象时不会影响到原始对象。
  • 下面是一个示例
    • 演示了如何使用copy模块中的deepcopy()函数进行深拷贝:
import copy

list1 = [1, 2, [3, 4]]
list2 = copy.deepcopy(list1)
  • 在这个例子中,我们创建了一个列表list1,其中包含一个嵌套列表。
  • 通过调用deepcopy()函数并将list1作为参数传递给它,我们可以创建一个名为list2的新对象,它是list1的深拷贝。
  • 现在,我们来演示深拷贝是如何避免原始对象的修改的:
list2[0] = 999
print(list1)  # 输出: [1, 2, [3, 4]]
print(list2)  # 输出: [999, 2, [3, 4]]
  • 可以看到,尽管我们修改了list2的第一个元素,但list1保持不变。
  • 这是因为list1list2是独立的对象,它们各自占用着不同的内存空间。

(2)浅拷贝:

  • 浅拷贝是指创建一个新对象,并将原始对象的元素复制到新对象中。
  • 然而
    • 如果原始对象包含可变的对象(如列表)
    • 则新对象中的这些元素仍然与原始对象中相应元素共享相同的内存地址。
  • 下面是一个示例
    • 演示了如何使用copy模块中的copy()函数进行浅拷贝:
import copy

list1 = [1, 2, [3, 4]]
list2 = copy.copy(list1)
  • 在这个例子中
    • 我们使用copy()函数创建了list1的浅拷贝list2
  • 让我们来看一下浅拷贝在修改可变对象时的行为:
list2[0] = 999
list2[2][0] = 777
print(list1)  # 输出: [1, 2, [777, 4]]
print(list2)  # 输出: [999, 2, [777, 4]]
  • 可以看到
    • 当我们修改list2中的第一个元素时
    • 只有list2受到影响
    • list1保持不变。
  • 但是
    • 当我们修改list2中嵌套列表的元素时
    • list1也会随之改变。
  • 这是因为浅拷贝只复制了列表的引用
    • 而没有创建新的内存空间来存储嵌套列表。

(3)综上所述

  • 深拷贝和浅拷贝在处理对象和数据结构时有不同的行为:
    • 深拷贝创建一个完全独立的对象,递归地复制所有嵌套对象。
    • 浅拷贝创建一个新对象,但它共享原始对象中可变对象的引用。

标签:对象,list1,list,深浅,拷贝,copy,original
From: https://www.cnblogs.com/Hqqqq/p/17963184

相关文章

  • 深拷贝和浅拷贝的问题 [补档-2022-10-22]
    简介:​ (在没有用户自己定义拷贝构造函数的情况下)编译器通过调用默认拷贝构造函数将一个对象的内容完整地复制到另一个对象上。如果我们要拷贝的对象它的成员有指针,并且指针指向着某一块空间,那么就要小心了。​通常我们创建一块动态空间,在不需要的时候会......
  • 如何防止U盘文件被拷贝?怎样保护U盘文件的安全?
    如何防止U盘文件被拷贝?怎样保护U盘文件的安全?在数字化时代,U盘已经成为我们日常生活和工作中不可或缺的存储工具。但是,随之而来的是U盘文件安全性的隐患。如何保护U盘文件的安全?下面,我们将从多个方面为你详细介绍,让你的U盘文件得到最好的保护。一、使用加密软件(例如:安企神软件)使用加......
  • C++ 拷贝构造函数
    拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:通过使用另一个同类型的对象来初始化新创建的对象。复制对象把它作为参数传递给函数。复制对象,并从函数返回这个对象。如果在类中没有定义拷......
  • Conan 拷贝依赖库到指定目录
    function(copy_shared_librariesCONAN_LIB_DIRSTARGET_DIR)foreach(LIB_DIR${CONAN_LIB_DIRS})file(GLOB_RECURSELIB_FILES${LIB_DIR}/*.so*)#使用通配符匹配所有可能的共享库文件foreach(LIB_FILE${LIB_FILES})#获取共享库文件名......
  • 文件批量拷贝的脚本(尤其适用于大小写敏感向不敏感的磁盘拷贝时发生冲突的情形)
    在Linux系统下,NTFS可以支持文件名大小写区分;但在MaxOS的exFAT格式中,则无法区分大小写。当从NTFS向exFAT拷贝文件时,当同一个目录下而在文件名相同但大小写不同的两个及以上文件时,向exFAT写入会中断,使得文件拷贝操作无法完成。因此,特别编写了下面这个脚本,用来解决这个问题。它可......
  • 【C++】STL 容器 - STL 容器的值语意 ( 容器存储任意类型元素原理 | STL 容器元素可拷
    文章目录一、STL容器的值(Value)语意1、STL容器存储任意类型元素原理2、STL容器元素可拷贝原理3、STL容器元素类型需要满足的要求4、STL容器迭代器遍历二、代码示例-自定义可存放入STL容器的元素类1、代码示例2、执行结果一、STL容器的值(Value)语意1、STL......
  • Python - 列表切片 与 深拷贝、浅拷贝
    1.列表list常用的方法:lst=[1,2,3]#append(new_item)方法相当于在列表末尾追加一个元素,相当于lst[len:]=new_itemlst.append(4)print(lst)#extend(iterable)方法,将iterable中的每个元素逐个添加到列表中,#相当于lst[len:len+len(iterable)]=iterablelst.e......
  • 拷贝文件到ubuntu服务器
    连接硬盘到Ubuntu服务器,用sudofdisk-l查看连接情况,如果没有显示出设备,那么换一个端口(USB口)试试挂载硬盘sudomkdirusbsudomount/dev/sdc2/home/usb查看当前所处目录的整个大小du-sh查看磁盘空间使用情况sudodf-h拷贝目录(包括子目录)文件到指定文件夹下  cd......
  • MySQL 8 剪切或拷贝用户创建语句
    有时,查看用户创建语句并将其复制到另一个数据库会很方便。比如在MySQL7中:mysql>showcreateusermytest@'%'\G***************************1.row***************************CREATEUSERformytest@%:CREATEUSER'mytest'@'%'IDENTIFIEDWITH'mys......
  • postgresql数据库迁移(拷贝数据库文件方式迁移)
    旧机器A:1、找到postgresql的data目录2、停止postgresql数据库3、执行tar-zcvfdatabak.tar.gzdata/新机器B:tar-zxvf databak.tar.gz-C/usr/local/postgres/使用scp或是ftp,或是移动硬盘将压缩文件放到新机器B上,前提条件是B机器要装有新的postgresql数据库,先停止数据库,然后找......