阐述引用、浅拷贝和深拷贝前,首先需要要了解 Python 的世界里,一切皆对象,每个对象各包含一个 idendity、type 和 value。

引用(Reference)

>>> b = [1 , 2]
>>> a = [b, 3, 4]
>>>
>>> c = a
>>> print c
[[1, 2], 3, 4]
>>> id(a)
4408148552
>>> id(c)
4408148552

c = a 表示 c 和 a 指向相同的地址空间,并没有创建新的对象。

浅拷贝(Shallow copy)

常见的浅拷贝的方法,是使用数据类型本身的构造器(list, tuple, dict, set),对于可变的序列(list, tuple),我们还可以通过切片操作符':'完成浅拷贝

当然,Python 中也提供了相对应的函数 copy.copy(),适用于任何数据类型。

>>> import copy
>>> d = copy.copy(a)
>>> print d
[[1, 2], 3, 4]
>>>
>>> id(a)
4408148552
>>> id(d)
4408199792
>>>
>>> id(a[0])
4408022944
>>> id(d[0])
4408022944
>>>
>>> d[0][0] = 5
>>> print a
>>> [[5, 2], 3, 4]

d = copy.copy(a) 创建了一个新对象,复制了原有对象的引用。

深拷贝(Deep copy)

是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。

>>> e = copy.deepcopy(a)
>>> print e
>>> [[1, 2], 3, 4]
>>>
>>> id(a)
>>> 4408148552
>>> id(e)
>>> 4408394792
>>>
>>> id(a[0])
>>> 4408022944
>>> id(e[0])
>>> 4408398432
>>>
>>> e[0][0] = 5
>>> print a
>>> [[1, 2], 3, 4]

e = copy.deepcopy(a) 新建了一个新对象,完整的在内存中复制原有对象。

Note

关于浅拷贝和深拷贝的区别,Python 的 document 是这样解释的:

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

使用深拷贝时,需要注意以下两个问题:

  • 递归对象拷贝: Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
  • 大对象拷贝: Because deep copy copies everything it may copy too much, e.g., administrative data structures that should be shared even between copies.

思考题

深度拷贝一个无限嵌套的列表。那么。当我们用等于操作符'=='进行比较时,输出会是什么呢?是 True 或者 False 还是其他?为什么呢?

import copy
x = [1]
x.append(x) y = copy.deepcopy(x) # 以下命令的输出是?
x == y

程序会报错:RecursionError: maximum recursion depth exceeded in comparison。因为x是一个无限嵌套的列表,y深度拷贝x也是一个无限嵌套的列表,理论上x==y应该返回True,但是x==y内部执行是会递归遍历列表x和y中每一个元素的值,由于x和y是无限嵌套的,因此会stack overflow,报错

参考

大部分内容参考了博客,在基础上做了补充。

python 进阶篇 浅拷贝与深拷贝的更多相关文章

  1. python进阶篇

    python进阶篇 import 导入模块 sys.path:获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到. ​ import sys ...

  2. Python 引用、浅拷贝、深拷贝解析

    引用 Python是动态数据类型的语言,故在对变量进行赋值时是不用制定变量类型的. 或者说,你可以把变量赋值的过程,当作是贴一个标签,去引用该数据. 看下面的例子: In [54]: a=4 In [ ...

  3. python赋值、浅拷贝、深拷贝区别

    在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出现一些问题.所以,在这里按个人的理解谈谈它们之间的区别. 一.赋值(assignment) 在<Py ...

  4. Python 赋值、浅拷贝和深拷贝

    初学Python,和C++还是有许多不同.直接赋值.浅拷贝和深拷贝,这三种拷贝对象的操作之间还是有许多的区别.Python语言的版本为2.7,在Pycharm中进行实验. 一.直接赋值 用下面的代码来 ...

  5. Python赋值、浅拷贝、深拷贝

    一.赋值(assignment) >>> a = [1, 2, 3] >>> b = a >>> print(id(a), id(b), sep= ...

  6. javascript篇-浅拷贝与深拷贝

    理解javascript 的浅拷贝与深拷贝,首先看一下js的数据类型: js有5种基本数据类型:undefined,null,boolean,number,string 还有一种复杂的数据类型(也叫引 ...

  7. python 基础之浅拷贝与深拷贝

    浅拷贝与深拷贝 1.普通赋值 例1: a = 15b = aa = 16print(b)#例2:lst1 = [1,2,3]lst2 = lst1lst1.append(4)print(lst2)#这 ...

  8. python中的浅拷贝,深拷贝

    直接引用,间接引用 # 1.列表存储的是索引对应值的内存地址,值会单独的开辟一个内存空间 list = ["a","b"] 内存里面存储的就是list[0],l ...

  9. python进阶(6)深拷贝和浅拷贝

    深拷贝和浅拷贝 不管对于浅拷贝.还是深拷贝,针对不可变对象str.int.tuple(有点特殊).boolean,它的内存地址是不变的,拷贝的仅仅是值 import copy a = 1 b = co ...

随机推荐

  1. 使用SlimYOLOv3框架实现实时目标检测

    介绍 人类可以在几毫秒内在我们的视线中挑选出物体.事实上,你现在就环顾四周,你将观察到周围环境并快速检测到存在的物体,并且把目光回到我们这篇文章来.大概需要多长时间? 这就是实时目标检测.如果我们能让 ...

  2. 推荐|近期热点机器学习git项目

    No1: InterpretML by Microsoft--Machine Learning Interpretability github地址:https://github.com/microso ...

  3. 计算机视觉基本原理——RANSAC

    公众号[视觉IMAX]第31篇原创文章 一 前言 对于上一篇文章——一分钟详解「本质矩阵」推导过程中,如何稳健地估计本质矩阵或者基本矩阵呢?正是这篇文章重点介绍的内容. 基本矩阵求解方法主要有: 1) ...

  4. 使用FME平移shapefile文件

  5. django中 对Mysql数据库的建表

    Django操作Mysql数据库: 1.1 在settings中,配置数据库相关参数,所以无需修改,这里我们看一下: DATABASES = { 'default': { # 这里可以指定使用的数据库 ...

  6. 15.自动部署web工程

    用maven自动部署web工程 在pom.xml中写入以下: <build> <!--最终名称,进入网页时有http://localhost:8080/xxx/--> < ...

  7. python 介绍,环境配置

    python介绍 介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,Guido开始写能够解释Python语言语法的解释器.Python这个名字,来 ...

  8. js之for与forEach循环的区别

    回武汉打卡第四天,武汉加油,逆战必胜!今天咱们探讨一下for循环和forEach()循环的区别. 首先,for循环在最开始执行循环的时候,会建立一个循环变量i,之后每次循环都是操作这个变量,也就是说它 ...

  9. Spring的IOC操作

    Spring的IOC操作 把对象的创建交给spring ioc操作两个部分 (1)ioc的配置文件方式 (2)ioc基于注解的方式 IOC 的底层原理 1.ioc底层原理使用技术 (1)xml配置文件 ...

  10. 第一次将本地项目push到github

    问题:github有一个空项目,将本地项目上传到github空项目时,报错如下 $ git push --set-upstream git@github.com:dslu7733/promise.gi ...