Python列表的深复制和浅复制示例详解
作者:Kepler11 发布时间:2023-01-29 01:26:47
一、深复制与浅复制
列表是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的一个引用。用一张图来解释:
那么修改l1也就是在修改l2:
接下来看一下创建l3的过程,l3 = l1[:] ,这是将l1进行切片,并将切片后的列表拷贝到l3所指向的内存区域,同样看图:
也就是说l1和l3指向不同的内存区域,那么修改l1并不会影响到l3:
通俗的来讲,像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,但是对列表中每个元素进行复制时进行的是浅复制呢?答案显而易见。
修改l1[3]中的元素:
三、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()在复制列表中的每个元素的时候,进行的是深拷贝。
总结
来源:https://blog.csdn.net/Kepler11/article/details/113785748
猜你喜欢
- 新建py文件,在里面写入Python代码,代码的功能是打印10次“Hello!”,将代码文件保存到桌面上:在命令行中运行Python脚本,并
- ALTER TABLE将表更改为当前字符集。如果在执行ALTER TABLE操作期间遇到重复键错误,原因在于新的字符集将2个键映射到了相同值
- 一、框架菜单1.1 common模块1.2 其他二、Excel接口测试案例编写三、读取Excel测试封装(核心封装)excel_utils.
- 目录1.事件循环2.协程和异步编程2.1 基本使用2.2 await2.3 Task对象1.事件循环可以理解成为一个死循环,去检查任务列表中
- SQL Server所谓的分布式查询(Distributed Query)是能够访问存放在同一部计算机或不同计算机上的SQL Server或
- 请先看看以下演示中的图案文字。这可不是图片效果,而是用CSS滤镜中的Chroma() 语句做成的文本文
- scrapy框架概述:Scrapy,Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数
- 透视表是一种可以对数据动态排布并且分类汇总的表格格式。对于熟练使用 excel 的伙伴来说,一定很是亲切!pd.pivot_table()
- 本文实例讲述了Python实现的爬取百度文库功能。分享给大家供大家参考,具体如下:# -*- coding: utf-8 -*-from s
- PHP echo() 函数实例输出一些文本:<?php echo "Hello world!"; ?>定义和
- 阅读上一篇:javascript面向对象编程(二) [Interface,Class.implement 接口及实现]接口规定了一些方法,如
- 本文实例讲述了python实现上传样本到virustotal并查询扫描信息的方法。分享给大家供大家参考。具体方法如下:import simp
- 在制作表单的时候,我们往往用CSS来重新定义表单元素(如输入框、按钮等)的样式,以便看起来更加美观。而表单中的很多不同元素(如输入框、提交按
- “用户体验(User Experience,简称UX 或 UE)是一种纯主观的在用户使用一个产品(服务)的过程中建立起来的心理感受。因为它是
- 最近,我喜欢上了XML编程,但又苦于它的美观程度又不够,找了许多书才搞定。 &n
- 经常在工作中会使用到XPath的相关知识,但每次总会在一些关键的地方不记得或不太清楚,所以免不了每次总要查一些零碎的知识,感觉即很烦又浪费时
- <div id="outer" style="background:#099"> cli
- 今天在做sql Server 2005的实验的时候碰到的问题,问题描述很清楚,怀疑是我以前给计算机修改了名称而导致的.可以用select @
- 现在有一个xml,格式如下: 代码如下:<date> <item> <id>&nbs
- 描述:让Len,Left,Right函数识别中文;对中文识别为两个字符,ASCII码为一个;可用此函数代替Len,Left,Right函数。