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如果对象中有引用其他的对象,如果对这个子对象进行修改,子对象的内容就会发生更改。

总结:

  1. 在简单对象中,无论是浅copy还是深copy,原对象里面元素的变化不会引起复制对象里面的元素的变化。
  2. 在复杂对象中,原对象的子对象元素发生变化,浅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的更多相关文章

  1. python学习笔记-(六)深copy&浅copy

    在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用. 1. 赋值 赋值其实只是传递对象引用,引用对象 ...

  2. python浅copy和深copy

    import   copy person =["name",[count,3000]] husband=copy.copy(person) wife=copy.copy(perso ...

  3. 浅copy 与 深copy

    import copy names = ["zhangyang", 'guyun', 'xiangpeng', ['jack','tom'], 'xuliangchen'] nam ...

  4. 【ObjectC—浅copy和深copy】

    一.OC设计copy的目的 为了能够从源对象copy一个新的对象副本,改变新对象(副本)的时候,不会影响到原来的对象. 二.实现copy协议 OC提供了两种copy方法:copy和mutableCop ...

  5. 浅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 ...

  6. Python中的浅复制、深复制

    参考 https://docs.python.org/3/library/copy.html?highlight=copy%20copy#copy.copy https://en.wikipedia. ...

  7. java深copy (伪深copy)【原】

    Teacher.java package test.clone; /** * 老师 * 深copy需要实现Cloneable接口 * @author King * */ public class Te ...

  8. [Python]Python中的浅复制与深复制

    看python的文档,发现list有copy方法,描述说效果同a[:]. 感觉有点惊讶,之前一直以为a[:]执行的是深复制. test了一下,发现确实如果a中存在可变对象,如list/set/dict ...

  9. python学习(28) 浅谈可变对象的单例模式设计

    python开发,有时候需要设计单例模式保证操作的唯一性和安全性.理论上python语言底层实现和C/C++不同,python采取的是引用模式,当一个对象是可变对象,对其修改不会更改引用的指向,当一个 ...

随机推荐

  1. spring的静态代理和动态代理

    Java静态代理 Jdk动态代理 java代理模式 即Proxy Pattern,23种java常用设计模式之一.代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问. 原理: 代理模式的主要 ...

  2. MySQL 存储过程参数用法 in, out, inout

    MySQL 存储过程参数有三种类型:in.out.inout.它们各有什么作用和特点呢? 一.MySQL 存储过程参数(in) MySQL 存储过程 “in” 参数:跟 C 语言的函数参数的值传递类似 ...

  3. pg按日,周,月进行数据统计

    pg数据库按周,月统计数据 SELECT date_trunc('WEEK', insert_time) as insertDate, SUM(data_increment) as dataTotal ...

  4. zDialog弹出层插件

    效果图如下: 提取自ZCMS的弹出框: 代替window.open.window.alert.window.confirm:提供良好的用户体验: 水晶质感,设计细腻,外观漂亮: 兼容ie6/7/8.f ...

  5. centos 6 安装python2.7和pip

    由于scrapy1.0的发布,想在Linux上测试,所以安装了centos6.6:但是它的python版本为2.6,很多东西都不支持,所以需要升级为2.7: 首先是在window7上安装虚拟机,然后安 ...

  6. Hive 导入、导出数据

    <------ 导入 ------> 从本地目录文件导入Hive表 语法:LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABL ...

  7. CAJ2PDF

    该项目不成熟,很容易遇到转换失败的例子. https://github.com/JeziL/caj2pdf https://github.com/JeziL/caj2pdf/wiki caj2pdf ...

  8. [嵌入式培训 笔记]-----Vim编辑器使用简介

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 第一讲小结 1. 光标在屏幕文本中的移动既 ...

  9. clipboard.js使用方法

    HTML data-clipboard-action=“ copy ”  或者“cut” data-clipboard-target="#domName" data-clipboa ...

  10. psd-面试-dp/LCS

    链接:https://www.nowcoder.com/acm/contest/90/D来源:牛客网 掌握未来命运的女神 psd 师兄在拿了朝田诗乃的 buff 后决定去实习. 埃森哲公司注册成立于爱 ...