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. 无法启动此程序,因为计算机丢失MSVCP120.dll

    这种错误是由于未安装** vcredist **引起的(而且版本是 2013版):https://www.microsoft.com/zh-CN/download/details.aspx?id=40 ...

  2. TensorFlow备忘录——conv2d函数

    卷积函数 TensorFlow学习备忘录 tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_forma ...

  3. php给图片添加圆角并且保持透明,可做圆形头像

      原文链接:https://www.zhaokeli.com/article/8031.html 给图片添加圆角, 用到的主要的(判断一个点是否在圆内)的公式在上面所说的生成圆形图片文章中. 然后扫 ...

  4. MySQL之长连接、短连接、连接池

    当数据库服务器和客户端位于不同的主机时,就需要建立网络连接来进行通信.客户端必须使用数据库连接来发送命令和接收应答.数据.通过提供给客户端数据库的驱动指定连接字符串后,客户端就可以和数据库建立连接了. ...

  5. Android Studio 3.0 及个版本下载和 gradle 各版本下载

    Android Studio 3.0 下载地址: 链接:http://pan.baidu.com/s/1jHVuOQi 密码:3pd0 Android Studio 3.0 包含了三大主要功能: 一套 ...

  6. 设计模式--门面模式C++实现

    门面模式C++实现 1定义facade 要求一个子系统的外部接口与其内部的通信必须通过一个统一的接口进行.门面模式提供一个高层次的接口,使得子系统更容易视同 注:门面模式注重统一对象,也就是提供一个访 ...

  7. yii2出现的400错误

    来一段百度来的正常解决方法,注意有很大的坑! 第一种解决办法是关闭Csrf 1配置文件关闭 2控制器里面关闭 public function init(){ $this->enableCsrfV ...

  8. ( 转)Sqlserver中tinyint, smallint, int, bigint的区别 及 10进制转换16进制的方法

    一.类型比较 bigint:从-2^63(-9223372036854775808)到2^63-1(9223372036854775807)的整型数据,存储大小为 8 个字节.一个字节就是8位,那么b ...

  9. 【2018多校第一场】hdu6308-Time Zone(日期)

    Problem Description Chiaki often participates in international competitive programming contests. The ...

  10. MoreEffectiveC++Item35(异常)(条款9-15)

    条款9 使用析构函数防止内存泄漏 条款10 在构造函数中防止内存泄漏 条款11 禁止异常信息传递到析构函数外 条款12 理解"抛出一个异常''与"传递一个参数"或调用一个 ...