python深拷贝和浅拷贝详解_Java浅拷贝和深拷贝的区别
2023-06-13 09:14:23 时间
大家好,又见面了,我是你们的朋友全栈君。
文章目录
1、Python 深拷贝和浅拷贝概念理解
- 浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。
- 深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。
2、浅拷贝
- 使用数据类型本身的构造器
- 对于可变的序列,还可以通过切片操作符 : 来完成浅拷贝
- Python 还提供了对应的函数 copy.copy() 函数,适用于任何数据类型
2.1 使用数据类型本身的构造器
list1 = [1, 2, 3]
list2 = list(list1)
print(list2)
print("list1==list2 ?",list1==list2)
print("list1 is list2 ?",list1 is list2)
set1= set([1, 2, 3])
set2 = set(set1)
print(set2)
print("set1==set2 ?",set1==set2)
print("set1 is set2 ?",set1 is set2)
dict1 = {
1:[1,'w'], 2:0, 3:98}
dict2 = dict(dict1)
print(dict2)
print("dict1 == dict2 ?",dict1 == dict2)
print("dict1 is dict2 ?",dict1 is dict2)
[1, 2, 3]
list1==list2 ? True
list1 is list2 ? False
{
1, 2, 3}
set1==set2 ? True
set1 is set2 ? False
{
1: [1, 'w'], 2: 0, 3: 98}
dict1 == dict2 ? True
dict1 is dict2 ? False
分析: 浅拷贝,为新变量重新分配一块内存,和原来变量的内存不一样,所以有
list1 is list2 ? False
set1 is set2 ? False
dict1 is dict2 ? False
但浅拷贝完,两个变量中的元素的值是一样的。
list1==list2 ? True
dict1 == dict2 ? True
set1==set2 ? True
2.2 对于列表
对于列表,还可以通过切片操作符“:”来完成浅拷贝
list1 = [1, 2, 3]
list2 = list1[:]
print(list2)
print("list1 == list2 ?",list1 == list2)
print("list1 is list2 ?",list1 is list2)
[1, 2, 3]
list1 == list2 ? True
list1 is list2 ? False
2.3 使用 copy.copy() 函数
函数 copy.copy() 函数,适用于任何数据类型
import copy
list1 = [1, 2, 3]
list2 = copy.copy(list1)
print(list2)
print("list1 == list2 ?",list1 == list2)
print("list1 is list2 ?",list1 is list2)
set1 = {
1, 2, 3}
set2 = copy.copy(set1)
print(set2)
print("set1 == set2 ?",set1 == set2)
print("set1 is set2 ?",set1 is set2)
dict1 = {
1:'xiaoming', 2:'xiahua',3:'xiaoli'}
dict2 = dict(dict1)
print(dict2)
print("dict1 == dict2 ?",dict1 == dict2)
print("dict1 is dict2 ?",dict1 is dict2)
[1, 2, 3]
list1 == list2 ? True
list1 is list2 ? False
{
1, 2, 3}
set1 == set2 ? True
set1 is set2 ? False
{
1: 'xiaoming', 2: 'xiahua', 3: 'xiaoli'}
dict1 == dict2 ? True
dict1 is dict2 ? False
2.4 对于元组
对于元组,使用 tuple() 或者切片操作符 ‘:’ 不会创建一份浅拷贝,相反它会返回一个指向相同元组的引用:
tuple1 = (1, 2, 3)
tuple2 = tuple(tuple1)
print(tuple2)
print("tuple1 == tuple2 ?",tuple1 == tuple2)
print("tuple1 is tuple2 ?",tuple1 is tuple2)
tuple1 = (1, 2, 3)
tuple2 = tuple1[:]
print(tuple2)
print("tuple1 == tuple2 ?",tuple1 == tuple2)
print("tuple1 is tuple2 ?",tuple1 is tuple2)
(1, 2, 3)
tuple1 == tuple2 ? True
tuple1 is tuple2 ? True
(1, 2, 3)
tuple1 == tuple2 ? True
tuple1 is tuple2 ? True
使用 tuple() 或者切片操作符 ‘:’ 不会创建一份浅拷贝,因为它开辟新的内存存储的是原对象的引用,而没有创建新的对象来存储原对象的子对象的引用,所以不是浅拷贝。相反它会返回一个指向相同元组的引用。
对字符串使用 str() 或者切片操作符 ‘:’,原理和 元组相同。
str1 = 'operation'
str2 = str1[:]
print(str2)
print("str1 == str2 ?",str1 == str2)
print("str1 is str2 ?",str1 is str2)
operation
str1 == str2 ? True
str1 is str2 ? True
str1 = 'operation'
str2 = str(str1)
print(str2)
print("str1 == str2 ?",str1 == str2)
print("str1 is str2 ?",str1 is str2)
operation
str1 == str2 ? True
str1 is str2 ? True
import copy
set1 = (1, 2, 3)
set2 = copy.copy(set1)
print(set2)
print("set1 == set2 ?",set1 == set2)
print("set1 is set2 ?",set1 is set2)
(1, 2, 3)
set1 == set2 ? True
set1 is set2 ? True
import copy
set1 = 'operation'
set2 = copy.copy(set1)
print(set2)
print("set1 == set2 ?",set1 == set2)
print("set1 is set2 ?",set1 is set2)
operation
set1 == set2 ? True
set1 is set2 ? True
也就是说,对字符串和元组使用 copy()、[:]、本身的构造器完成的复制,都只是开辟了内存存储原对象的引用,而不是存储原对象的子对象的引用。
2.5 关于切片操作符 ‘:’
切片操作符 ‘:’ 不能用于字典和集合完成浅拷贝
# set1 = {1, 2, 3}
# set2 = set1[:]
# dict1 = {1:1, 2:2, 3:3}
# dict2 = dict1[:]
2.6 和赋值的区别
和赋值的本质区别在于,赋值只是把原对象的引用给到新对象
set1 = {
1:1, 2:2, 3:3}
set2 = set1
print(set2)
print("set1 == set2 ?",set1 == set2)
print(id(set1))
print(id(set2))
{
1: 1, 2: 2, 3: 3}
set1 == set2 ? True
2515252654368
2515252654368
2.7 浅拷贝需注意的问题
对数据采用浅拷贝的方式时,如果原对象中的元素不可变,那倒无所谓;但如果元素可变,浅拷贝通常会出现一些问题,
list1 = [[1, 2], (30, 40)]
list2 = list(list1)
list1.append(100)
print("list1:",list1)
print("list2:",list2)
list1[0].append(3)
print("list1:",list1)
print("list2:",list2)
list1[1] += (50, 60)
print("list1:",list1)
print("list2:",list2)
list1: [[1, 2], (30, 40), 100]
list2: [[1, 2], (30, 40)]
list1: [[1, 2, 3], (30, 40), 100]
list2: [[1, 2, 3], (30, 40)]
list1: [[1, 2, 3], (30, 40, 50, 60), 100]
list2: [[1, 2, 3], (30, 40)]
2、深拷贝
Python 中以 copy.deepcopy() 来实现对象的深度拷贝
import copy
list1 = [[1, 2], (30, 40)]
list2 = copy.deepcopy(list1)
list1.append(100)
print("list1:",list1)
print("list2:",list2)
list1[0].append(3)
print("list1:",list1)
print("list2:",list2)
list1[1] += (50, 60)
print("list1:",list1)
print("list2:",list2)
list1: [[1, 2], (30, 40), 100]
list2: [[1, 2], (30, 40)]
list1: [[1, 2, 3], (30, 40), 100]
list2: [[1, 2], (30, 40)]
list1: [[1, 2, 3], (30, 40, 50, 60), 100]
list2: [[1, 2], (30, 40)]
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/203548.html原文链接:https://javaforall.cn
相关文章
- Java多线程详解_java支持多线程
- JAVA三元运算符_java中三元运算符详解
- 二级java程序设计--Java SDK6.0的下载和操作[通俗易懂]
- java解析xml方法_详解Java解析XML的四种方法
- java random函数原理_详解JAVA中Random()函数的用法
- java 把对象转成map_Java对象转换成Map[通俗易懂]
- java random函数用法_JAVA的Random类的用法详解[通俗易懂]
- java判断一个对象是否为空_Java中判断对象是否为空的方法的详解
- Java详解:淘宝秒杀脚本java
- python hashlib_Python hashlib模块实例使用详解
- java有什么作用_Java有什么用「建议收藏」
- java代码大全及详解_Java练级攻略[通俗易懂]
- java axis_Java 使用Axis实现WebService实例
- 【Python】python文件打开方式详解——a、a+、r+、w+、rb、rt区别[通俗易懂]
- java平均的随机数_Java 随机数详解「建议收藏」
- Python标识符的命名规则,下列哪些是对的?_python标识符不能使用关键字
- java事务_Java 事务详解[通俗易懂]
- Python 人气王,JS 比 Java 更受公司青睐详解编程语言
- Java学习笔记之一java关键字及作用详解编程语言
- 51 Nod 1005 大数加法Java大数乱搞,python大数乱搞详解编程语言
- 小白的Python之路 day5 python模块详解及import本质编程语言
- .NET/ASP.NET/C#/WCF/SQL Server/My SQL/Java/JSP/JDBC/Spring/Spring MVC/PHP/Python/Ruby/Shell/Agile/CSS/HTML/HTTP/Unix/Linux大量PDF书籍/电子书籍下载, Effective Java 下载详解编程语言
- Python玩转Redis:提升缓存效率(python使用redis)
- Java调用Linux库实现跨系统功能(java调用linux库)
- Linux下编译Java文件,迎来新体验(linux编译java文件)
- 使用Java语言写Redis实现一个分布式缓存系统(用java写个redis)