1. 赋值:简单的对象引用

在python中,变量赋值实际上是简单的对象引用。在创建一个对象后,再把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是简单地拷贝了这个对象的引用。

(1)原子类型的赋值

>>> x = 3.14
>>> y = x
>>> x,y
(3.14, 3.14)
>>> id(x),id(y)
(84759984L, 84759984L)>>> x = 1.414
>>> x,y
(1.414, 3.14)
>>> id(x),id(y)
(84759912L, 84759984L)
  • 这里的 x = 3.14 创建了一个浮点型对象(值为3.14)并将这个浮点型对象的引用赋给 x
  • 然后 y = x 创建了一个指向同一个对象的别名y,事实上并没有为y创建一个新的浮点型对象
  • 接着 x = 1.414 又创建了一个新的浮点型对象(值为1.414)并将这个新的浮点型对象的引用赋给了 x ,此时并没有改变y指向的值为3.14的浮点型对象
  • 用个图示来表示能更直观的理解:

(2)非原子类型的赋值

>>> A = [10,[20,30]]
>>> B = A# 改变前:
>>> A,B
([10, [20, 30]], [10, [20, 30]])
>>> id(A),id(B)
(91063304L, 91063304L)
>>> [id(x) for x in A],[id(x) for x in B]
([84836720L, 90951880L], [84836720L, 90951880L])>>> A[0] = 100
>>> A[1][1] = 300# 改变后:
>>> A,B
([100, [20, 300]], [100, [20, 300]])
>>> id(A),id(B)
(91063304L, 91063304L)
>>> [id(x) for x in A],[id(x) for x in B]
([90004016L, 90951880L], [90004016L, 90951880L])
  • 可以看到,第二行代码的赋值操作后,A和B的内存地址都是一样的,包括子元素的内存地址也都是一样的
  • 当改变A的内容的时候,改变的是A所指向的对象的内容,由于B也是指向这个对象的,因此B的内容也会跟着一起改变
  • 用个图示来表示能更直观的理解:

2. 浅拷贝

在python中,对一个对象进行浅拷贝,产生的对象是新的,其类型和原对象一样;但其内容不是新的,只是原对象的内容的引用。

(1)举个例子来理解

>>> import copy
>>> A = [10,[20,30]]
>>> B = copy.copy(A)# 改变前:
>>> A,B
([10, [20, 30]], [10, [20, 30]])
>>> id(A),id(B)
(99615944L, 99670792L)
>>> [id(x) for x in A],[id(x) for x in B]
([91055472L, 99617160L], [91055472L, 99617160L])>>> A[0] = 100
>>> A[1][1] = 300# 改变后:
>>> A,B
([100, [20, 300]], [10, [20, 300]])
>>> id(A),id(B)
(99615944L, 99670792L)
>>> [id(x) for x in A],[id(x) for x in B]
([91057296L, 99617160L], [91055472L, 99617160L])
  • 不多说了,直接上图理解吧:

(2)浅拷贝的方式

上面例子中使用了copy模块中的copy函数来实现浅拷贝,其实python中以下这这几种方式来实现浅拷贝:

  • 完全切片操作:B = A[:]
  • 利用工厂函数:B = list(A)B = dict(A)
  • 使用copy模块的copy函数:B = copy.copy(A)

3. 深拷贝

对于浅拷贝中的例子,如果希望修改 A[1] 的内容时 B[1] 的内容不跟着一起改变,就需要用到深拷贝:copy.deepcopy()

>>> import copy
>>> A = [10,[20,30]]
>>> B = copy.deepcopy(A)# 改变前:
>>> A,B
([10, [20, 30]], [10, [20, 30]])
>>> id(A),id(B)
(88462536L, 88478856L)
>>> [id(x) for x in A],[id(x) for x in B]
([80176496L, 88463752L], [80176496L, 88514952L])>>> A[0] = 100
>>> A[1][1] = 300# 改变后:
>>> A,B
([100, [20, 300]], [10, [20, 30]])
>>> id(A),id(B)
(88462536L, 88478856L)
>>> [id(x) for x in A],[id(x) for x in B]
([80178320L, 88463752L], [80176496L, 88514952L])

不多说了,也直接上图理解吧:

4. 注意

  • 非容器类型(比如数字、字符串和其他“原子”类型的对象,像xrange对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成的
  • 如果tuple变量只包含原子类型对象,对它的深拷贝将不会进行 (另外,tuple的元素是不能修改的)
  • 将上面深拷贝的例子中的list类型改为tuple类型,即便使用深拷贝,也只能得到一个浅拷贝:
>>> import copy
>>> A = [10,(20,30),[40,50]]
>>> B = copy.deepcopy(A)
>>> A,B
([10, (20, 30), [40, 50]], [10, (20, 30), [40, 50]])
>>> [id(x) for x in A],[id(x) for x in B]
([80045424L, 85975112L, 85961096L], [80045424L, 85975112L, 86012552L])
>>> A[1][1]
30
>>> A[1][1] = 300
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment>>> del A
>>> del B>>> A = [10,([20,30],40),[50,60]]
>>> B = copy.deepcopy(A)
>>> A,B
([10, ([20, 30], 40), [50, 60]], [10, ([20, 30], 40), [50, 60]])
>>> [id(x) for x in A],[id(x) for x in B]
([80045424L, 85960712L, 85959880L], [80045424L, 85960328L, 86014920L])
>>> A[1][1] = 400
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> A[1][0] = 200
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> A[1][0][1] = 300
>>> A,B
([10, ([20, 300], 40), [50, 60]], [10, ([20, 30], 40), [50, 60]])
>>> [id(x) for x in A],[id(x) for x in B]
([80045424L, 85960712L, 85959880L], [80045424L, 85960328L, 86014920L])

参考书:《python核心编程(第二版)》,人民邮电出版社,p50,p156-158

python中对象的赋值、浅拷贝和深拷贝相关推荐

  1. python中的引用、浅拷贝和深拷贝

    在python中,有一句话:"一切皆为对象,一切皆为对象的引用",所以 只要记住这句话就很容易清楚python中的引用.浅拷贝和深拷贝了. 1. 引用 python中的引用是经常使 ...

  2. Python中的对象引用、浅拷贝与深拷贝

    最近项目中遇到一个Python浅拷贝机制引起的bug,由于对于Python中对象引用.赋值.浅拷贝/深拷贝机制没有足够的认识,导致调试了很久才发现问题,这里简单记录一下相关概念. 在Python的设计 ...

  3. python中的复制、浅拷贝和深拷贝的区别

    (1)直接复制:传递对象的引用(该引用指向变量的存储地址),若原始值改变,则被赋值的b也会做出相同的改变. b = alist (2)浅拷贝:使用copy库中的copy函数,只拷贝父对象,不拷贝子对象 ...

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

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

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

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

  6. python中copy模块的使用,深拷贝和浅拷贝

    python中copy模块的使用,深拷贝和浅拷贝 文章目录: 一.copy模块的介绍 1.copy模块 二.copy模块的使用 拓展说明: 1.id( )函数的使用 2.is和== 的区别 pytho ...

  7. 引用拷贝、对象拷贝、浅拷贝、深拷贝 到底是什么【详细例子介绍】

    首先要知道的: Java的数据类型分为基本数据类型和引用数据类型. 拷贝一个对象,可以使用 Cloneable接口的clone()方法. 对象拷贝分为 浅拷贝 和 深拷贝,这两种拷贝都是从引用拷贝 引 ...

  8. python中对象的定义_python中对象的定义和使用

    python中对象的定义和使用 发布时间:2020-06-22 11:57:16 来源:亿速云 阅读:98 作者:Leah 今天就跟大家聊聊有关python中对象的定义和使用,可能很多人都不太了解,为 ...

  9. python中给变量赋值时、既确定了变量的值_Python 中的变量赋值不需要类型声明,可以直接赋值,通过值来决定变量的类型。_学小易找答案...

    [单选题]"阴阳离决.精气乃绝"所反映的阴阳关系是 [单选题]在Photoshop通道种类中不包括( ). [单选题]国家垄断资本主义的主要形式是(). [判断题]Python 中 ...

最新文章

  1. C++读写ini配置文件GetPrivateProfileString()WritePrivateProfileString()
  2. 在一家开源公司工作的体验!
  3. openfiler 搭建虚拟存储 并 配置服务端 (转载)
  4. 自行开发驱动如何进行驱动签名
  5. SQL SERVER 中 GO 的用法2
  6. Oracle11gR2_ADG管理之恢复主库的truncate表实战
  7. python 面对对象思维导图_Python面向对象思维导图
  8. LNMP3.0一键安装
  9. JAVA ANDROID SOCKET通信检测(SERVER)连接是否断开
  10. TED如何和压力做朋友(第四天完)
  11. Spring 揭秘 12.1
  12. CRMEB 知识付费模版消息修改教程
  13. 定位误差:基准位置公差、基准不重合误差
  14. Excel取整函数汇总
  15. openwrt 中 Luci 的简单使用
  16. python中的乘方_python乘方运算
  17. 基于u-net,cv2以及cnn的中文车牌定位,矫正和端到端识别软件
  18. 计算机考试成绩80分是统计指标值,某同学计算机考试成绩80分,这是统计指标值。...
  19. WAF(网络应用防火墙)是什么
  20. 均值滤波器类型_滤波电路的作用及四种基本类型

热门文章

  1. MX25上SD卡的插拨检测机制
  2. 最佳开源PHP开发工具
  3. ES6特性:Promise
  4. Google Hacking使用详解
  5. C# 编写的 64位操作系统 - MOOS
  6. adb shell cmd appops
  7. TP-LINK路由器配置
  8. 用word字体转换来代替手写作业--最详细
  9. ​【​观察】云栖大会共话JDM模式 揭秘创新背后的价值和启示
  10. MFC 获取屏幕客户区(及显示器大小)