Python中级之深浅拷贝
1825 字
9 分钟
Python中级之深浅拷贝
【一】深浅拷贝问题引入
- 无论深拷贝还是浅拷贝都是用来 复制对象的
- 如果是浅copy,只会复制一层,如果copy的对象中有可变数据类型,修改可变数据类型还会影响拷贝的对象
- 如果是深copy,完整复制,无论可变或不可变,都是创建出新的来,以后再改原对象,都不会对copy出的对象造成影响
- 在Python中,深拷贝和浅拷贝是用于复制对象的两种不同的方式。
list_original = [1, 2, 3, [4, 5, 6, ]]list_copy = list_originalprint(list_copy is list_original)# True- 通过将list_copy赋值为list_original,实际上是将list_copy和list_original指向相同的内存地址。
- 所以list_copy is list_original的结果为True,表示它们是同一个对象的两个引用。
- 因此对list_copy或list_original的修改都会影响到另一个。
【1】浅拷贝
- 浅拷贝仅复制对象的一层内容,如果对象中包含了可变数据类型(如列表、字典等),则拷贝的对象将与原对象共享这些可变数据类型的引用。
- 这意味着对于原对象中的可变数据类型进行修改操作时,拷贝的对象也会受到影响。
import copy
# 原对象original_list = [1, 2, [3, 4]]# 使用浅拷贝创建拷贝对象copied_list = copy.copy(original_list)
# 修改原对象中的可变数据类型original_list[2].append(5)
print("原对象:", original_list)print("拷贝对象:", copied_list)- 可以看到,尽管只修改了原对象中的可变数据类型(子列表),但拷贝对象也被修改了。
- 这是因为浅拷贝仅复制了列表的第一层,而对于内部的子列表,拷贝对象和原对象共享同一个引用。
from copy import copy
list_original = [1, 2, 3, [4, 5, 6, ]]
# 使用`copy()`函数进行浅拷贝时,创建了一个新的列表对象`list_copy_two`,并复制了原始列表`list_original`中的元素。# 这意味着`list_copy_two`和`list_original`是两个独立的对象,分别指向不同的内存地址。list_copy_two = copy(list_original)
# 对于嵌套的可变对象(如列表),浅拷贝只会复制其引用,而不会创建新的内存空间。print(list_copy_two is list_original)# False
# 因此,`list_copy_two`中的嵌套列表仍然指向相同的地址# 所以对`list_copy_two`中嵌套的列表进行修改 , 也会影响到原始的列表`list_original`。list_copy_two[3][1] = 999print(list_original)# [1, 2, 3, [4, 999, 6]]print(list_copy_two)# [1, 2, 3, [4, 999, 6]]- 使用copy()函数进行浅拷贝时
- 创建了一个新的列表对象list_copy_two,并复制了原始列表list_original中的元素。
- 这意味着llist_copy_two和list_original是两个独立的对象,分别指向不同的内存地址。
- 然而,对于嵌套的可变对象(如列表)
- 浅拷贝只会复制其引用
- 而不会创建新的内存空间。
- 因此,list_copy_two中的嵌套列表仍然指向相同的地址
- 所以对list_copy_two中嵌套的列表进行修改
- 也会影响到原始的列表list_original。
(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] = 888print(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] = 999print(list1) # 输出: [1, 2, [3, 4]]print(list2) # 输出: [999, 2, [3, 4]]- 可以看到,尽管我们修改了list2的第一个元素,但list1保持不变。
- 这是因为list1和list2是独立的对象,它们各自占用着不同的内存空间。
(2)浅拷贝:
- c
- 下面是一个示例
- 演示了如何使用copy模块中的copy()函数进行浅拷贝:
import copy
list1 = [1, 2, [3, 4]]list2 = copy.copy(list1)- 在这个例子中
- 我们使用copy()函数创建了list1的浅拷贝list2。
- 让我们来看一下浅拷贝在修改可变对象时的行为:
list2[0] = 999list2[2][0] = 777print(list1) # 输出: [1, 2, [777, 4]]print(list2) # 输出: [999, 2, [777, 4]]- 可以看到
- 当我们修改list2中的第一个元素时
- 只有list2受到影响
- 而list1保持不变。
- 但是
- 当我们修改list2中嵌套列表的元素时
- list1也会随之改变。
- 这是因为浅拷贝只复制了列表的引用
- 而没有创建新的内存空间来存储嵌套列表。
(3)综上所述
- 深拷贝和浅拷贝在处理对象和数据结构时有不同的行为:
- 深拷贝创建一个完全独立的对象,递归地复制所有嵌套对象。
- 浅拷贝创建一个新对象,但它共享原始对象中可变对象的引用。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
相关文章智能推荐
1
C 语言发展史
编程语言了解 C 语言从 BCPL、B 语言到现代标准 C 的发展历程、核心特点与应用领域。
2
C 语言开发环境的安装与配置
编程语言在 Windows、Linux 与 macOS 上安装 C 工具链,配置编辑器,并编译运行第一个 C 程序。
3
C 语言初识:程序运行机制与基本结构
编程语言认识 C 程序从源代码到运行的完整流程,以及基础语法和程序的基本结构。
4
C 语言基础:注释、关键字、变量与数据类型
编程语言学习 C 语言的注释、关键字、标识符、常量、变量和基本数据类型等基础知识。
5
C 语言数据类型
编程语言理解 C 语言的数据类型体系,包括基本类型、整数类型、浮点类型和逻辑类型。
随机文章随机推荐














