Python中的赋值、浅拷贝、深拷贝介绍

 更新时间:2015年03月09日 11:56:09   投稿:junjie  
这篇文章主要介绍了Python中的赋值、浅拷贝、深拷贝介绍,Python中也分为简单赋值、浅拷贝、深拷贝这几种“拷贝”方式,需要的朋友可以参考下

和很多语言一样,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作为例子。

二、浅拷贝

复制代码 代码如下:

>>> a = ['hello', [123, 234]]
>>> b = a[:]
>>> [id(x) for x in a,b]
[4496003656, 4496066752]
>>> [id(x) for x in a]
[4496091584, 4495947536]
>>> [id(x) for x in b]
[4496091584, 4495947536]

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

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

复制代码 代码如下:

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

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

三、深拷贝

复制代码 代码如下:

>>> from copy import deepcopy
>>> a = ['hello', [123, 234]]
>>> b = deepcopy(a)
>>> [id(x) for x in a, b]
[4496066824, 4496066680]
>>> [id(x) for x in a]
[4496091584, 4496067040]
>>> [id(x) for x in b]
[4496091584, 4496371792]

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

修改a的值后:

复制代码 代码如下:

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

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

总结:

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

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

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

相关文章

  • python NetworkX库生成并绘制带权无向图

    python NetworkX库生成并绘制带权无向图

    这篇文章主要为大家介绍了python NetworkX库生成并绘制带权无向图的实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Python的Lambda函数用法详解

    Python的Lambda函数用法详解

    在Python中有两种函数,一种是def定义的函数,另一种是lambda函数,也就是大家常说的匿名函数。这篇文章主要介绍了Python的Lambda函数用法,需要的朋友可以参考下
    2019-09-09
  • PyCharm的设置方法和第一个Python程序的建立

    PyCharm的设置方法和第一个Python程序的建立

    今天小编就为大家分享一篇PyCharm的设置方法和第一个Python程序的建立,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01
  • python3安装speech语音模块的方法

    python3安装speech语音模块的方法

    今天小编就为大家分享一篇python3安装speech语音模块的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • Python实现列表删除重复元素的三种常用方法分析

    Python实现列表删除重复元素的三种常用方法分析

    这篇文章主要介绍了Python实现列表删除重复元素的三种常用方法,结合实例形式对比分析了Python针对列表元素的遍历、判断、转换等相关操作技巧,需要的朋友可以参考下
    2017-11-11
  • python退出循环的方法

    python退出循环的方法

    在本篇文章里小编给大家整理的是关于python如何退出循环的相关知识点内容,需要的朋友们可以参考下。
    2020-06-06
  • python cv2图像质量压缩的算法示例

    python cv2图像质量压缩的算法示例

    使用opencv对图像进行编码,一方面是图像二进制传输的需要,另一方面对图像压缩。本文主要介绍了python cv2图像质量压缩的算法示例,感兴趣的可以了解一下
    2021-06-06
  • python使用OS模块操作系统接口及常用功能详解

    python使用OS模块操作系统接口及常用功能详解

    os是 Python 标准库中的一个模块,提供了与操作系统交互的功能,在本节中,我们将介绍os模块的一些常用功能,并通过实例代码详细讲解每个知识点
    2023-06-06
  • 基于PyQt5完成的PDF拆分功能

    基于PyQt5完成的PDF拆分功能

    这篇文章主要介绍了基于PyQt5完成的PDF拆分功能,本文介绍的pdf拆分功能还有一些待完善地方,例如可增加预览功能,实现每页预览,以及如何实现多条件拆分,需要的朋友可以参考下
    2022-06-06
  • python将ip地址转换成整数的方法

    python将ip地址转换成整数的方法

    这篇文章主要介绍了python将ip地址转换成整数的方法,涉及Python针对IP地址的转换技巧,需要的朋友可以参考下
    2015-03-03

最新评论