Python学习-赋值、浅copy和深copy
Python Copy:
在Python语言中,分为浅拷贝和深拷贝两种形式,也就是官方文档中的Shadow copy和Deep copy。在对简单的对象(object)进行复制时,两者没有区别,如下面的代码所示:
#简单对象的浅copy和深copy对比
import copy
list1 = [1,2,3,4,5]
#浅复制
Shadow_copy_list1 = copy.copy(list1)
print(list1) #[1, 2, 3, 4, 5]
print(Shadow_copy_list1) #[1, 2, 3, 4, 5]
#对原对象元素进行修改:列表末尾添加'6'
list1.append(6)
print(list1) #[1, 2, 3, 4, 5, 6]
print(Shadow_copy_list1) #[1, 2, 3, 4, 5]
print(id(list1)) #地址:
print(id(Shadow_copy_list1)) #地址: #深复制
Deep_copy_list1 = copy.deepcopy(list1)
print(list1) #[1, 2, 3, 4, 5]
print(Deep_copy_list1) #[1, 2, 3, 4, 5]
#对原对象元素进行修改:列表末尾添加'6'
list1.append(6)
print(list1) #[1, 2, 3, 4, 5, 6]
print(Deep_copy_list1) #[1, 2, 3, 4, 5] print(id(list1)) #地址:
print(id(Deep_copy_list1)) #地址:
从简单对象的浅copy和深copy可以看出,对原列表中的元素进行修改,copy的对象里面的元素不会发生改变。
对于浅copy和深copy,在复杂对象的copy中会有所区别,如下程序所示:
#复杂对象的浅copy和深copy对比
import copy
list1 = [1,2,3,[4,5]]
#浅copy
Shadow_copy_list1 = copy.copy(list1)
list1[3][0] = 7
print(list1) #[1, 2, 3, [7, 5]]
print(Shadow_copy_list1) #[1, 2, 3, [7, 5]]
print(id(list1)) #地址:
print(id(Shadow_copy_list1)) #地址: list1[3][0] = 4 #将列表恢复为初始列表
#深copy
Deep_copy_list1 = copy.deepcopy(list1)
list1[3][0] = 7
print(list1) #[1, 2, 3, [7, 5]]
print(Deep_copy_list1) #[1, 2, 3, [4, 5]]
print(id(list1)) #地址:
print(id(Deep_copy_list1)) #地址:
从复杂对象的浅copy和深copy可以看出,当浅copy时,如果对复杂对象的子对象元素进行修改,原列表和copy的列表里面的子对象元素都会产生变化,但是当深copy时,若复杂对象的子对象元素发生了变化,copy的对象的所有元素都不会发生变化。这是什么原因呢,这是因为浅拷贝只复制一层对象的属性,而深复制则递归复制了所有层级。
1、copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
2、copy.deepcopy 深拷贝 拷贝对象及其子对象
(深copy)
深copy新建一个对象重新分配内存地址,在内存中生成完全一模一样的内容。
(浅copy)
浅copy也会对复制后的列表重新分配内存地址。但是在浅copy中,对于列表里面的元素,浅copy复制的是元素的内存地址,相当于引用,此时的子对象属于公共对象,浅copy如果对象中有引用其他的对象,如果对这个子对象进行修改,子对象的内容就会发生更改。
总结:
- 在简单对象中,无论是浅copy还是深copy,原对象里面元素的变化不会引起复制对象里面的元素的变化。
- 在复杂对象中,原对象的子对象元素发生变化,浅copy的对象里面的子对象元素也会产生变化,此时该子对象相当于镜像文件,对于引用它的对象,都会产生影响,而在深copy中,由于深copy是对所有的元素进行了复制,所以原对象里面子对象元素的变化不会导致复制对象里面元素的变化。
Python 赋值:
简单对象的赋值、浅copy和深copy对比:
#简单对象的赋值、浅copy和深copy对比
import copy
list1 = [1,2,3,4,5]
New_list1 = list1
Shadow_copy_list1 = copy.copy(list1)
Deep_copy_list1 = copy.deepcopy(list1)
#对原对象元素进行修改:列表末尾添加'6'
list1.append(6)
#原列表
print(list1) #[1, 2, 3, 4, 5, 6]
print(id(list1)) #地址:1913255661704
#赋值列表
print(New_list1) #[1, 2, 3, 4, 5, 6]
print(id(New_list1)) #地址:1913255661704
#浅copy列表
print(Shadow_copy_list1) #[1, 2, 3, 4, 5]
print(id(Shadow_copy_list1)) #地址:1913255661896
#深copy列表
print(Deep_copy_list1) #[1, 2, 3, 4, 5]
print(id(Deep_copy_list1)) #地址:1913255663176
从程序运行结果可以看出,简单对象中,若原列表元素发生改变,则通过赋值的新列表元素也会改变,而浅copy和深copy的列表元素均不会发生变化。可以认为赋值是将原对象上贴上两个标签,如程序中的list1标签和New_list1两个标签,使用的也是内存中的同一块地址,列表中元素的变化,则两个list均会产生变化。而使用copy进行复制的则不同了,不管是浅copy和深copy,都会重新在内存中分配一块地址,这样原列表中元素的变化,复制的列表中不会产生变化。
复杂对象的赋值、浅copy和深copy对比:
#复杂对象的赋值、浅copy和深copy对比
import copy
list1 = [1,2,3,[4,5]]
New_list1 = list1
Shadow_copy_list1 = copy.copy(list1)
Deep_copy_list1 = copy.deepcopy(list1)
#对原对象元素进行修改:将列表中第4个元素中的'4'更改为'7'
list1[3][0] = 7
#原列表
print(list1) #[1, 2, 3, [7, 5]]
print(id(list1)) #地址:1975516434760
#赋值列表
print(New_list1) #[1, 2, 3, [7, 5]]
print(id(New_list1)) #地址:1975516434760
#浅copy列表
print(Shadow_copy_list1) #[1, 2, 3, [7, 5]]
print(id(Shadow_copy_list1)) #地址:1975516436040
#深copy列表
print(Deep_copy_list1) #[1, 2, 3, [4, 5]]
print(id(Deep_copy_list1)) #地址:1975516435976
从程序运行结果可以看出,对复杂对象的子对象元素进行修改时,通过赋值的列表与浅copy的列表中的子对象也会随之改变,因为此时复杂对象中的子对象作为公共对象,浅copy时,新的列表还是引用的原列表中的子对象。而深copy则不一样,深copy是进行递归复制的,将列表的所有层都进行了复制,所以原列表中子对象元素的变化不会导致深copy的列表中的子对象的变化。
初学者,如有分析的不正确的地方,欢迎交流讨论。
Python学习-赋值、浅copy和深copy的更多相关文章
- python学习笔记-(六)深copy&浅copy
在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用. 1. 赋值 赋值其实只是传递对象引用,引用对象 ...
- python浅copy和深copy
import copy person =["name",[count,3000]] husband=copy.copy(person) wife=copy.copy(perso ...
- 浅copy 与 深copy
import copy names = ["zhangyang", 'guyun', 'xiangpeng', ['jack','tom'], 'xuliangchen'] nam ...
- 【ObjectC—浅copy和深copy】
一.OC设计copy的目的 为了能够从源对象copy一个新的对象副本,改变新对象(副本)的时候,不会影响到原来的对象. 二.实现copy协议 OC提供了两种copy方法:copy和mutableCop ...
- 浅copy与深copy举例
例1: #!/usr/bin/env python import copy d1 = {'x':1,'y':2,'z':[3,4.5]} d2 = d1 d3 = d1.copy() d4 = co ...
- Python中的浅复制、深复制
参考 https://docs.python.org/3/library/copy.html?highlight=copy%20copy#copy.copy https://en.wikipedia. ...
- java深copy (伪深copy)【原】
Teacher.java package test.clone; /** * 老师 * 深copy需要实现Cloneable接口 * @author King * */ public class Te ...
- [Python]Python中的浅复制与深复制
看python的文档,发现list有copy方法,描述说效果同a[:]. 感觉有点惊讶,之前一直以为a[:]执行的是深复制. test了一下,发现确实如果a中存在可变对象,如list/set/dict ...
- python学习(28) 浅谈可变对象的单例模式设计
python开发,有时候需要设计单例模式保证操作的唯一性和安全性.理论上python语言底层实现和C/C++不同,python采取的是引用模式,当一个对象是可变对象,对其修改不会更改引用的指向,当一个 ...
随机推荐
- shell基本认识
shell基本认识 bash # echo $BASH /bin/bash 第一个shell脚本first_shell.sh #!/bin/bash echo "Hello world!&q ...
- KVM irqfd and ioeventfd
In previous article vhost architecture we mentioned that vhost and the guest signal each other by ir ...
- 在网页链接中打开qq或者微信
打开微信: 先说第一种,大家知道,在自己的微信资料里有个二维码,别人扫描后可以查看你的资料添加你,把二维码扫描后,得到的地址是:http://weixin.qq.com/r/ykzexmzEPzFAr ...
- centos 6 安装python2.7和pip
由于scrapy1.0的发布,想在Linux上测试,所以安装了centos6.6:但是它的python版本为2.6,很多东西都不支持,所以需要升级为2.7: 首先是在window7上安装虚拟机,然后安 ...
- 转:在Eclipse的Debug页签中设置虚拟机参数
http://blog.csdn.net/decorator2015/article/details/50914479 在Eclipse的Debug页签中设置虚拟机参数 步骤 1,Run->De ...
- Project facet Java 1.8 is not supported by target runtime Apache Tomcat v7.0.
找到项目下的“.settings”
- 【Error】:10061由于目标计算机积极拒绝,无法连接
之前Windows上连接mongodb的时候首先用mongod.exe启动程序之后,用mongo.exe来连接数据库.但是在连接的时候,出现如下错误: error:10061 由于目标计算机积极拒绝, ...
- 012PHP基础知识——运算符(五)
<?php /** * 运算符的短路: * && 逻辑与 || 逻辑或 存在短路: */ /* $a = 1; $a==1 ||$c=100; //逻辑或:第一个表达式返回tru ...
- 分析器错误信息: 未能加载类型“xxx.Global”。
Global.asax错误 分析器错误 说明: 在分析向此请求提供服务所需资源时出错.请检查下列特定分析错误详细信息并适当地修改源文件. 分析器错误信息: 未能加载类型“xxx.Global”. 源错 ...
- C#学习历程(三)[基础概念]
>>简单描述OOP 面向对象编程是由面向过程编程发展而来,不再注重于具体的步骤,而是更多的聚焦于对象. 以对象为载体,然后去完善对象的特点(属性),然后实现对象的具体的功能,同时处理对象与 ...