一、赋值(assignment)

  1. >>> a = [1, 2, 3]
  2. >>> b = a
  3. >>> print(id(a), id(b), sep='\n')
  4. 139701469405552
  5. 139701469405552

  

在Python中,用一个变量给另一个变量赋值,其实就是给当前内存中的对象增加一个“标签”而已。

如上例,通过使用内置函数 id() ,可以看出 a 和 b 指向内存中同一个对象。a is b会返回 True 。

二、浅拷贝(shallow copy)

注意:浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。

所谓“浅拷贝”,是指创建一个新的对象,其内容是原对象中元素的引用。(拷贝组合对象,不拷贝子对象)

常见的浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。

  1. >>> a = [1, 2, 3]
  2. >>> b = list(a)
  3. >>> print(id(a), id(b)) # a和b身份不同
  4. 140601785066200 140601784764968
  5. >>> for x, y in zip(a, b): # 但它们包含的子对象身份相同
  6. ... print(id(x), id(y))
  7. ...
  8. 140601911441984 140601911441984
  9. 140601911442016 140601911442016
  10. 140601911442048 140601911442048

  

三、深拷贝(deep copy)

所谓“深拷贝”,是指创建一个新的对象,然后递归的拷贝原对象所包含的子对象。深拷贝出来的对象与原对象没有任何关联。

深拷贝只有一种方式:copy模块中的deepcopy函数。

  1. >>> import copy
  2. >>> a = [1, 2, 3]
  3. >>> b = copy.deepcopy(a)
  4. >>> print(id(a), id(b))
  5. 140601785065840 140601785066200
  6. >>> for x, y in zip(a, b):
  7. ... print(id(x), id(y))
  8. ...
  9. 140601911441984 140601911441984
  10. 140601911442016 140601911442016
  11. 140601911442048 140601911442048

  

看了上面的例子,有人可能会疑惑:

为什么使用了深拷贝,a和b中元素的id还是一样呢?

答:这是因为对于不可变对象,当需要一个新的对象时,python可能会返回已经存在的某个类型和值都一致的对象的引用。而且这种机制并不会影响 a 和 b 的相互独立性,因为当两个元素指向同一个不可变对象时,对其中一个赋值不会影响另外一个。

我们可以用一个包含可变对象的列表来确切地展示“浅拷贝”与“深拷贝”的区别:

  1. >>> import copy
  2. >>> a = [[1, 2],[5, 6], [8, 9]]
  3. >>> b = copy.copy(a) # 浅拷贝得到b
  4. >>> c = copy.deepcopy(a) # 深拷贝得到c
  5. >>> print(id(a), id(b)) # a 和 b 不同
  6. 139832578518984 139832578335520
  7. >>> for x, y in zip(a, b): # a 和 b 的子对象相同
  8. ... print(id(x), id(y))
  9. ...
  10. 139832578622816 139832578622816
  11. 139832578622672 139832578622672
  12. 139832578623104 139832578623104
  13. >>> print(id(a), id(c)) # a 和 c 不同
  14. 139832578518984 139832578622456
  15. >>> for x, y in zip(a, c): # a 和 c 的子对象也不同
  16. ... print(id(x), id(y))
  17. ...
  18. 139832578622816 139832578621520
  19. 139832578622672 139832578518912
  20. 139832578623104 139832578623392

  

从这个例子中可以清晰地看出浅拷贝与深拷贝地区别。

总结:

1、赋值:简单地拷贝对象的引用,两个对象的id相同。
2、浅拷贝:创建一个新的组合对象,这个新对象与原对象共享内存中的子对象。
3、深拷贝:创建一个新的组合对象,同时递归地拷贝所有子对象,新的组合对象与原对象没有任何关联。虽然实际上会共享不可变的子对象,但不影响它们的相互独立性。

浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。

Python赋值、浅拷贝、深拷贝的更多相关文章

  1. python中赋值-浅拷贝-深拷贝之间的关系

    赋值: 变量的引用,没有拷贝空间 对象之间赋值本质上 是对象之间的引用传递而已.也就是多个对象指向同一个数据空间. 拷贝的对象分两种类型: . 拷贝可变类型 浅拷贝: 只拷贝第一层数据,不关心里面的第 ...

  2. python 中的 赋值 浅拷贝 深拷贝

    1.对象的赋值 都是进行对象引用(内存地址)传递,即 b is a ,a 变 b也变 2.浅拷贝 会创建一个新的对象,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址) 当我们使用下面的操作 ...

  3. python赋值,深拷贝和浅拷贝的区别

    1.赋值 list1=[[1,2],'fei',66] list2=list1 list1 [[1, 2], 'fei', 66] list2 [[1, 2], 'fei', 66] list2.ap ...

  4. 搞不懂JS中赋值·浅拷贝·深拷贝的请看这里

    前言 百科定义:拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这 ...

  5. Python对象拷贝——深拷贝与浅拷贝

    对象赋值 浅拷贝 深拷贝 1. 对象赋值 对象的赋值实际上是对对象的引用.也就是说当把一个对象赋值给另一个对象时,只是拷贝了引用.如: >>> t1 = tuple('furzoom ...

  6. Python中的赋值、深拷贝与浅拷贝(内存地址)

    Python中的赋值.深拷贝与浅拷贝(内存地址) 1.python中的可变对象与不可变对象 (1) 可变对象:dict,list def dict_test(): a = {} b = a print ...

  7. 对Python中列表和数组的赋值,浅拷贝和深拷贝的实例讲解

    引用:https://www.jb51.net/article/142775.htm 列表赋值: 1 2 3 4 5 6 7 >>> a = [1, 2, 3] >>&g ...

  8. 深度解析:python之浅拷贝与深拷贝

    深度解析python之浅拷贝与深拷贝 本文包括知识点: 1.copy与deepcopy 2.可变类型与不可变类型 1.copy与deepcopy 在日常python编码过程中,经常会遇见变量的赋值.这 ...

  9. **Python中的深拷贝和浅拷贝详解

    Python中的深拷贝和浅拷贝详解   这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容.   要说清楚Python中的深浅拷贝,需要 ...

  10. JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘

    一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...

随机推荐

  1. noi.ac #39 MST

    MST 模板题 #include <iostream> #include <cstdio> #include <algorithm> #include <cm ...

  2. 9.11 myl模拟赛

    9.11 myl 模拟赛 100 + 100 + 0 第一题耗费了太多的时间,导致最后一题没有时间想,直接去写了暴力,而且出题人没有给暴力分.... Problem 1. superman [题目描述 ...

  3. BZOJ 1857: [Scoi2010]传送带

    二次联通门 : BZOJ 1857: [Scoi2010]传送带 /* BZOJ 1857: [Scoi2010]传送带 三分套三分 可能是吧..dalao们都说明显是一个单峰函数 可是我证不出来.. ...

  4. Mac zsh 所有命令失效

    正在配置一些东西,然后zsh的所有命令不能用了. 我艹...... 然后一顿猛查,发现有个命令好使,记录一下 在命令行只想输入下面命令 PATH=/bin:/usr/bin:/usr/local/bi ...

  5. Iptables之一基本应用

    Firewall :防火墙,隔离工具 工作于主机或网络的边缘,对于进出本主机或网络的报文根据事先定义好的检查规则作匹配检测,对于能够被规则所匹配到的报文做出相应处理的组件 主机防火墙 网络防火墙 ID ...

  6. Java ArrayList对象集合去重

    import java.util.ArrayList; import java.util.Iterator; public class StringSampleDemo { public static ...

  7. 搭建K8S集群

    一.前言 我们将现有的虚拟机称之为Node1,用作主节点.为了减少工作量,在Node1安装Kubernetes后,我们利用VirtualBox的虚拟机复制功能,复制出两个完全一样的虚拟机作为工作节点. ...

  8. ls命令的简单实现

    ls命令的简单实现 目标:简单的实现ls命令 实现的mic_ls命令主要功能 1.循环遍历目录 2.列出目标目录所有的子目录和文件 3.列出文件的文件权限,所有者,文件大小等详细信息 参数 -r 循环 ...

  9. [spring-boot] 健康状况监控

    pom文件 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>s ...

  10. Laravel中的Storage::disk

    Laravel中的Storage::disk 一.总结 一句话总结: Storage的disk的路径和file的路径都是一回事,都是config/filesystems.php配置文件中disks 比 ...