和很多语言一样,Python中也分为简单赋值、浅拷贝、深拷贝这几种“拷贝”方式。

  在学习过程中,一开始对浅拷贝理解很模糊。不过经过一系列的实验后,我发现对这三者的概念有了进一步的了解。

  一、赋值

  赋值算是这三种操作中最常见的了,我们通过一些例子来分析下赋值操作:

  str例

>>> a = 'hello'
>>> b = 'hello'
>>> c = a
>>> [id(x) for x in a,b,c]
[4404120000, 4404120000, 4404120000]

  由以上指令中,我们可以发现a, b, c三者的地址是一样的。所以以上赋值的操作就相当于c = a = b = 'hello'。

  赋值是系统先给一个变量或者对象(这里是'hello')分配了内存,然后再将地址赋给a, b, c。所以它们的地址是相同的。

  list例

>>> a = ['hello']
>>> b = ['hello']
>>> c = a
>>> [id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]

  但是这种情况却不一样了,a和b的地址不同。为何?

  因为str是不可变的,所以同样是'hello'只有一个地址,但是list是可变的,所以必须分配两个地址。

  这时,我们希望探究以上两种情况如果修改值会如何?

  str例

>>> a = 'world'
>>> [id(x) for x in a,b,c]
[4404120432, 4404120000, 4404120000]
>>> print a, b, c
world hello hello

  这时a的地址和值变了,但是b, c地址和值都未变。因为str的不可变性,a要重新赋值则需重新开辟内存空间,所以a的值改变,a指向的地址改变。b, c由于'hello'的不变性,不会发生改变。

  list例

>>> a[0] = 'world'
>>> [id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]
>>> print a, b, c
['world'] ['hello'] ['world']

  这时a, c的值和地址均改变,但二者仍相同,b不改变。由于list的可变性,所以修改list的值不需要另外开辟空间,只需修改原地址的值。所以a, c均改变。


  在了解了以上的不同点之后,我们就能很好地分析浅拷贝和深拷贝了。

  我们均用list作为例子。

  二、浅拷贝

1 >>> a = ['hello', [123, 234]]
2 >>> b = a[:]
3 >>> [id(x) for x in a,b]
4 [4496003656, 4496066752]
5 >>> [id(x) for x in a]
6 [4496091584, 4495947536]
7 >>> [id(x) for x in b]
8 [4496091584, 4495947536]

  Line3,4可以看出a, b地址不同,这符合list是可变的,应开辟不同空间。那浅拷贝就是拷贝了一个副本吗?再看Line5 - 8,我们发现a, b中元素的地址是相同的。如果说字符串'hello'地址一致还能理解,但是第二个元素是list地址仍一致。这就说明了浅拷贝的特点,只是将容器内的元素的地址复制了一份。

  接着我们尝试修改a, b中的值:

1 >>> a[0] = 'world'
2 >>> a[1].append(345)
3 >>> print 'a = ', a, '\n\r', 'b = ', b
4 a =  ['world', [123, 234, 345]]
5 b =  ['hello', [123, 234, 345]]

  a中第一个元素str改变,但是b中未改变;a中第二个元素改变,b中也改变。这就符合不可变的对象修改会开辟新的空间,可变的对象修改不会开辟新空间。也进一步证明了浅拷贝仅仅是复制了容器中元素的地址。


  二、深拷贝

1 >>> from copy import deepcopy
2 >>> a = ['hello', [123, 234]]
3 >>> b = deepcopy(a)
4 >>> [id(x) for x in a, b]
5 [4496066824, 4496066680]
6 >>> [id(x) for x in a]
7 [4496091584, 4496067040]
8 >>> [id(x) for x in b]
9 [4496091584, 4496371792]

  深拷贝后,可以发现a, b地址以及a, b中元素地址均不同。这才是完全拷贝了一个副本。

  修改a的值后:

1 >>> a[0] = 'world'
2 >>> a[1].append(345)
3 >>> print 'a = ', a, '\n\r', 'b = ', b
4 a =  ['world', [123, 234, 345]]
5 b =  ['hello', [123, 234]]

  从Line4,5中可以发现仅仅a修改了,b没有任何修改。因为b是一个完全的副本,元素地址均与a不同,a修改,b不受影响。


  总结:

  1. 赋值是将一个对象的地址赋值给一个变量,让变量指向该地址(旧瓶装旧酒)。

  2. 浅拷贝是在另一块地址中创建一个新的变量或容器,但是容器内的元素的地址均是源对象的元素的地址的拷贝。也就是说新的容器中指向了旧的元素(新瓶装旧酒)。

  3. 深拷贝是在另一块地址中创建一个新的变量或容器,同时容器内的元素的地址也是新开辟的,仅仅是值相同而已,是完全的副本。也就是说(新瓶装新酒)。

转载于:https://www.cnblogs.com/PythonMrChu/p/10673507.html

Python——赋值、浅拷贝、深拷贝相关推荐

  1. Interview:算法岗位面试—10.11下午—上海某公司算法岗位(偏机器学习,互联网数字行业)技术面试考点之XGBoost的特点、python的可变不可变的数据类型、赋值浅拷贝深拷贝区别

    ML岗位面试:10.11下午-上海某公司算法岗位(偏机器学习,互联网数字行业)技术面试考点之XGBoost的特点.python的可变不可变的数据类型.赋值浅拷贝深拷贝区别 Interview:算法岗位 ...

  2. python赋值浅拷贝和深拷贝的区别_python赋值、浅拷贝、深拷贝区别

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

  3. 一文搞懂JS中的赋值·浅拷贝·深拷贝

    前言 为什么写拷贝这篇文章?同事有一天提到了拷贝,他说赋值就是一种浅拷贝方式,另一个同事说赋值和浅拷贝并不相同.我也有些疑惑,于是我去MDN搜一下拷贝相关内容,发现并没有关于拷贝的实质概念,没有办法只 ...

  4. python赋值浅拷贝和深拷贝的区别_浅拷贝、深拷贝和普通赋值操作有什么区别?...

    对于不可变对象,创建副本没有多大意义,因为它们不会改变.对于可变对象^{},^{}和^{}的行为不同.让我们用例子来讨论它们. 赋值操作只是将源的引用赋值给目标,例如:>>> i = ...

  5. python3 赋值 浅拷贝 深拷贝 简介

    目录 一.赋值 二.浅拷贝(shallow copy) 三.深拷贝(deep copy) 四.关于拷贝操作的警告 一.赋值 在python中,对象的赋值就是简单的对象引用,这点和C++不同.如下: a ...

  6. 彻底理解Python中浅拷贝和深拷贝的区别

    目录 前言 1. 浅拷贝和深拷贝的概念 2. is和==的区别 3. 赋值操作 4. copy模块里面的copy()方法 5. copy模块里面的deepcopy()方法 6.字典自带的copy方法 ...

  7. python中有那几种赋值_详解Python列表赋值复制深拷贝及5种浅拷贝

    概述 在列表复制这个问题,看似简单的复制却有着许多的学问,尤其是对新手来说,理所当然的事情却并不如意,比如列表的赋值.复制.浅拷贝.深拷贝等绕口的名词到底有什么区别和作用呢? 列表赋值 # 定义一个新 ...

  8. python深浅拷贝 面试_[面试题二]百度资深面试官:python赋值、浅拷贝与深拷贝

    内存管理相关的面试一直是面试中的重点考察内容.赋值.深拷贝与浅拷贝是日常编码工作中,需要时常关注的知识点.不小心可是会写出bug哦- 赋值 先来看一段代码,下面两段代码的输出结果会是什么呢? # ca ...

  9. Python 玩转数据 5 - 图解 Python 赋值,浅拷贝 copy.copy() 和 深拷贝 copy.deepcopy() 原理

    引言 上面文章有介绍 Python 动态类型 共享引用等相关知识,有这个基础,我们来深入研究一下 Python 赋值,拷贝的原理,有涉及到可变类型和不可变类型的不同处理.更多 Pyton 进阶系列文章 ...

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

    对Python中列表和数组的赋值,浅拷贝和深拷贝的实例讲解 列表赋值: >>> a = [1, 2, 3] >>> b = a >>> print ...

最新文章

  1. Pycharm 修改tab缩进快捷键
  2. python初学者视频-python从入门到精通视频(全60集)
  3. 【原创】android——SQLite的cmd命令的基本操作
  4. 结构化并发应用程序——任务执行
  5. 带有Spring Security的OAuth 2.0快速指南
  6. DotNET内存管理与垃圾回收[转]
  7. 程序员想早点下班被经理拒绝,一气之下要辞职,经理慌了
  8. jsp内置对象作业3-application用户注册
  9. 职业年金退休能拿多少?怎么算的?
  10. 个人技能总结7--Apache服务器反向代理,负载均衡,热备份+Tomcat配置
  11. 创建美区苹果账户ID
  12. 激光雷达产业深度研究报告:三大思考
  13. 计算机软件行业新三板企业,2017福布斯值得关注的新三板企业榜:软件行业、互联网服务占据大半...
  14. Java-基础篇-03-【选择语句-循环语句-随机数】
  15. go语言教程哪里有?go 语言优秀开源项目汇总
  16. 近期购书体验:当当相对最棒,卓越蜗牛,京东缺货
  17. 网站运营的十二条盈利模式
  18. 深入理解网络通信与tcp/ip协议
  19. Poemscape|Beta阶段事后诸葛亮
  20. 东方财富板块资金python抓取

热门文章

  1. Ajax搜索结果页面下方的分页按钮的生成
  2. 测试上传图片晰度+测试多数量图片上传
  3. Android 颜色设置:透明度换算
  4. Calibre-免费开源的“一站式”的电子书管理阅读格式转换软件
  5. android studio如何生成混淆代码的jar
  6. android webView的使用
  7. 有可能在onPause之前调用onSaveInstanceState
  8. Fibonacci数列第n项的log(n)算法
  9. Flutter:实现红包晃动效果
  10. 《学习之道》第六章关注过程,亦培养习惯