Python列表的深复制和浅复制示例详解


Posted in Python onFebruary 12, 2021

一、深复制与浅复制

列表是Python中自带的一种数据结构,在使用列表时,拷贝操作不可避免,下面简单讨论一下列表的深复制(拷贝)与浅复制

首先看代码:

l1 = [5, 4, 3, 2, 1]
# 用两种方法实现对列表l1的拷贝
l2 = l1
l3 = l1[:]
print(l1) # [5, 4, 3, 2, 1]
print(l2) # [5, 4, 3, 2, 1]
print(l3) # [5, 4, 3, 2, 1]
 
#修改l1
l1[0] = 9
print(l1) # [9, 4, 3, 2, 1]
print(l2) # [9, 4, 3, 2, 1]
print(l3) # [5, 4, 3, 2, 1]

我们发现修改l1的第一个元素后,l2的第一个元素跟着改变,而l3并没有发生变化。Python内置函数id()可以返回元素的地址,那么我们使用这个函数来看一下三个列表的地址:

print(id(l1)) # 2927957162504
print(id(l2)) # 2927957162504
print(id(l3)) # 2927923243528

从结果来看,l1和l2地址是一样的,也就是说l1和l2指向的是同一块内存区域,显然,通过 l2 = l1 操作,l1和l2都成了指向同一块内存地址的“指针”,也就是说这个操作是为l1取了一个别名,也可以说l2是l1的一个引用。用一张图来解释:

Python列表的深复制和浅复制示例详解

那么修改l1也就是在修改l2:

Python列表的深复制和浅复制示例详解

接下来看一下创建l3的过程,l3 = l1[:] ,这是将l1进行切片,并将切片后的列表拷贝到l3所指向的内存区域,同样看图:

Python列表的深复制和浅复制示例详解

也就是说l1和l3指向不同的内存区域,那么修改l1并不会影响到l3:

Python列表的深复制和浅复制示例详解

通俗的来讲,像l2这种,拷贝出来的对象和原对象的地址相同,为浅复制,像l3这种,分配新的内存空间并拷贝原始内容的,拷贝出来的对象和原对象的地址不同,为深复制

二、复制列表内元素的浅复制

在复制列表中的所有元素的时候,进行浅复制

看一个比较有意思的东西,看代码:

l1 = [1,2,3,[1,3]]
l2 = l1[:]
l1[3][1] = 9
print(l1) # [1, 2, 3, [1, 9]]
print(l2) # [1, 2, 3, [1, 9]]

按照前面的理解,修改l1某个元素后,l2应该不会发生改变,可结果却与我们预想的结果大相径庭,于是,我们不得不思考一下l2深复制到底复制了什么东西。实际上列表其实可以理解为一个“指针”,l1[3]是一个列表元素,l2[3]也是一个列表元素,执行以下代码:

print(id(l2[3])) # 2014816956232
print(id(l1[3])) # 2014816956232

我们发现l1[3]和l2[3]指向的地址是一样的,也就是说在执行 l2 = l1[:] 的时候,将一个地址拷贝了,所以修改l1[3]相当于修改l2[3],所以才会出现上述结果,这更加说明了列表其实就是一个指向一片内存区域的“指针”。那么我们是不是可以说列表l2深复制l1,但是对列表中每个元素进行复制时进行的是浅复制呢?答案显而易见。

Python列表的深复制和浅复制示例详解

修改l1[3]中的元素:

Python列表的深复制和浅复制示例详解

三、copy()和deepcopy()

copy模块可以帮助我们实现对象的复制操作

列举一下其他的拷贝列表的方式:

l4 = l1 * 1
print(id(l4)) # 2927957916296
l5 = list(l1)
print(id(l5)) # 2927957767816
import copy
l6 = copy.copy(l1)
print(id(l6)) # 2927956854024
l7 = copy.deepcopy(l1)
print(id(l7)) # 2927958503368

我们可以看到,这几种拷贝方式所得到的的新对象与原对象的地址都不相同了,并没有按照字面意思(copy进行浅复制,deepcopy进行深复制),那么copy()和deepcopy()究竟有什么区别呢,继续看代码:

list1 = [1,2,3,[1,3]]
list2 = list1[:]
list3 = copy.copy(list1)
list4 = copy.deepcopy(list1)
list1[3][0] = 9
print(list1) # [1, 2, 3, [9, 3]]
print(list2) # [1, 2, 3, [9, 3]]
print(list3) # [1, 2, 3, [9, 3]]
print(list4) # [1, 2, 3, [1, 3]]
print(id(list1[3])) # 2927923172616
print(id(list2[3])) # 2927923172616
print(id(list3[3])) # 2927923172616
print(id(list4[3])) # 2927967190728

可以发现copy()和前面提到的用 [:] 进行拷贝没有本质上的区别,对列表中的每个元素进行复制时进行的是浅拷贝,而deepcopy()在复制列表中的每个元素的时候,进行的是深拷贝

Python列表的深复制和浅复制示例详解

Python列表的深复制和浅复制示例详解

总结

到此这篇关于Python列表的深复制和浅复制的文章就介绍到这了,更多相关Python列表深复制和浅复制内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python求pi的方法
Oct 08 Python
用Python制作简单的钢琴程序的教程
Apr 01 Python
举例讲解Python设计模式编程中的访问者与观察者模式
Jan 26 Python
Python中类的初始化特殊方法
Dec 01 Python
Redis使用watch完成秒杀抢购功能的代码
May 07 Python
PyQt5+requests实现车票查询工具
Jan 21 Python
详解如何用python实现一个简单下载器的服务端和客户端
Oct 28 Python
Django 实现Admin自动填充当前用户的示例代码
Nov 18 Python
PyTorch: Softmax多分类实战操作
Jul 07 Python
浅析Python 责任链设计模式
Sep 11 Python
Python 实现集合Set的示例
Dec 21 Python
基于Python实现的购物商城管理系统
Apr 27 Python
Python就将所有的英文单词首字母变成大写
Feb 12 #Python
详解Java中一维、二维数组在内存中的结构
Feb 11 #Python
SpringBoot首页设置解析(推荐)
Feb 11 #Python
使用Python爬取小姐姐图片(beautifulsoup法)
Feb 11 #Python
详解python日志输出使用配置文件格式
Feb 10 #Python
python 获取域名到期时间的方法步骤
Feb 10 #Python
Numpy ndarray 多维数组对象的使用
Feb 10 #Python
You might like
简单的cookie计数器实现源码
2013/06/07 PHP
php Xdebug的安装与使用详解
2013/06/20 PHP
PHP中Trait及其应用详解
2017/02/14 PHP
关于jquery.validate1.9.0前台验证的使用介绍
2013/04/26 Javascript
基于AngularJs + Bootstrap + AngularStrap相结合实现省市区联动代码
2016/05/30 Javascript
Angular下H5上传图片的方法(可多张上传)
2017/01/09 Javascript
jq stop()和:is(:animated)的用法及区别(详解)
2017/02/12 Javascript
HTML5+jQuery实现搜索智能匹配功能
2017/03/24 jQuery
vue动态生成dom并且自动绑定事件
2017/04/19 Javascript
微信小程序上传多图到服务器并获取返回的路径
2019/05/05 Javascript
layui table 获取分页 limit的方法
2019/09/20 Javascript
js实现转动骰子模型
2019/10/24 Javascript
解决Vue打包上线之后部分CSS不生效的问题
2019/11/12 Javascript
只有 20 行的 JavaScript 模板引擎实例详解
2020/05/11 Javascript
[02:35]DOTA2英雄基础教程 末日使者
2013/12/04 DOTA
[01:05:59]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.22
2019/09/05 DOTA
python支持断点续传的多线程下载示例
2014/01/16 Python
Python面向对象程序设计示例小结
2019/01/30 Python
Python Pandas中根据列的值选取多行数据
2019/07/08 Python
PyCharm 配置远程python解释器和在本地修改服务器代码
2019/07/23 Python
使用Python实现正态分布、正态分布采样
2019/11/20 Python
PYQT5开启多个线程和窗口,多线程与多窗口的交互实例
2019/12/13 Python
Python类中self参数用法详解
2020/02/13 Python
Python操作MySQL数据库的示例代码
2020/07/13 Python
高街生活方式全球在线商店:AZBRO
2017/08/26 全球购物
次世代生活态度:Hypebeast
2018/07/05 全球购物
巴基斯坦购物网站:Goto
2019/03/11 全球购物
SQL Server笔试题
2012/01/10 面试题
写好自荐信的要点
2013/11/06 职场文书
优秀党员获奖感言
2014/02/18 职场文书
法定代表人身份证明书
2014/09/10 职场文书
部队2014年终工作总结
2014/11/27 职场文书
机器人瓦力观后感
2015/06/12 职场文书
2019年行政人事个人工作总结范本!
2019/07/19 职场文书
Python破解极验滑动验证码详细步骤
2021/05/21 Python
Redis实战高并发之扣减库存项目
2022/04/14 Redis