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采取的是引用模式,当一个对象是可变对象,对其修改不会更改引用的指向,当一个 ...
随机推荐
- Android DB那些事-数据库加密
说到数据库加密,目前最好且唯一的方案就是SqlCipher对sqlite3整体加密,微信也用的它.开源,且支持很多平台. 单就Android来说,集成不算太麻烦,1个jar包,3个so库,1个zip. ...
- PHP stream相关协议及上下文选项和参数归纳
支持的协议和封装协议 PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen(). copy(). file_exists() 和 filesize() 的文件系统函数. 除了这些封装协 ...
- Python中 如何使用telnet 检测端口是否通
import tn=telnetlib.Telnet(host,port)不报异常则该端口是通的,可结合try进行使用
- 英语每日阅读---5、VOA慢速英语(翻译+字幕+讲解):美国人口普查局表示美国人受教育程度提升
英语每日阅读---5.VOA慢速英语(翻译+字幕+讲解):美国人口普查局表示美国人受教育程度提升 一.总结 一句话总结: a.Thirty-four percent - college degree: ...
- String类的subString(a,b)方法(基于jdk 1.9)
基于上文:http://www.jianshu.com/p/a20ee3bb9c1b public String substring(int beginIndex, int endIndex) { i ...
- spring mvc: rss(xml)输出
准备: rss包插件 Rome 库及其依赖项rome-utils,jdom和slf4j <!-- rss源依赖 --> <!-- https://mvnrepository.com/ ...
- linux入门总结
linux的核心概念知识: linux软件是开源免费的,而linux是由Unix演变而成,Unix是由MINIX演变而成. 2000年以后,linux系统日趋成熟,涌现大量基于linux服务平 ...
- centos静默安装oracle12c
配置系统和安装所需软件包 关闭selinux 临时关闭(不用重启) [root@SVR-3-125 ~]# setenforce 0 修改配置文件(需要重启): 将SELINUX=enforcing ...
- 优化JDBC封装
可重用性较强的JDBC封装 以下为代码,注释中写了主要思想 主类 com.util.JDBCUtil.java package com.util; import java.lang.reflect.F ...
- 【javascript基础】 广告嵌套document.write的非iframe方式的延迟加载
用ControlJS优化阿里妈妈广告http://ued.taobao.com/blog/2011/03/controljs-alimama/让document.write的广告无阻塞的加载http: ...