Python 列表的切片和赋值操作很基础,之前也遇到过一些坑,以为自己很懂了。但今天刷 Codewars 时发现了一个更大的坑,故在此记录。

Python 列表赋值:复制“值”还是“引用”?

很多入门 Python 的人会犯这样一个错误:在赋值操作=中搞不清是赋了“值”还是“引用”。比如:

a = [1, 2, 3]
b = a
b[0] = 10 # 更改列表 b 的第一个元素,但 a 现在也被更改为了 [10, 2, 3]

他可能只想改变列表b,但实际上这样也会改变列表a

因为b实际上是列表a的另一个引用ab是同一个对象,id(a) == id(b),所以更改b也会更改a。这个应该大部分人都知道。所以正确的代码应该使用切片来进行列表的复制

a = [1, 2, 3]
b = a[:] # 使用切片进行列表复制
b[0] = 10 # 此时 a 和 b 是两个不同的对象

二维列表引发的思考:列表的本质

好的,现在我们确定切片能够进行列表的复制。那我们就能心安理得地改动新的列表了吗?请看二维列表(二维数组):

a = [[1, 2, 3], [4, 5, 6]]
b = a[:]
b[0][0] = 10

此时,a还是被改动了!

原因是,虽然id(a) == id(b)Falseab确实不是同一个对象。但它们的元素都是同一个对象——id(a[0]) == id(b[0])id(a[1]) == id(b[1])。因为列表里存储的是对象的引用!

列表 list 终究只是个容器。就像 tuple 本身是 immutable (不可变)的,但它只是容器,它可以存储一个可变对象,因此呈现出一种可以被改动的“假象”。例如:

>>> a = ([1],)
>>> a[0][0] = 2
>>> a
([2],)

所以容器和它存储的对象不能混为一谈。所以对于这种二维列表,想要进行完全的复制,请直接使用copy.deepcopy()深度复制。

如果只想复制一部分(切片),那可以先复制再切片:

>>> import copy
>>> a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> b = copy.deepcopy(a)[1:]
>>> b[0][0] = 100 >>> a
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> b
[[100, 5, 6], [7, 8, 9]]

此时修改b没有影响到a

Python 列表切片陷阱:引用、复制与深复制的更多相关文章

  1. Python赋值、浅复制和深复制

    Python赋值.浅复制和深复制 ​ 首先我们需要知道赋值和浅复制的区别: 赋值和浅复制的区别 赋值,当一个对象赋值给另一个新的变量时,赋的其实是该对象在栈中的地址,该地址指向堆中的数据.即赋值后,两 ...

  2. Python中的浅复制、深复制

    参考 https://docs.python.org/3/library/copy.html?highlight=copy%20copy#copy.copy https://en.wikipedia. ...

  3. Java中引用的浅复制和深复制

    Java中除了基本类型int,char,double等的赋值是按照值传递之外,其余的类型和对象都是按照引用进行传递的. 下面来看一个关于引用的例子. package referenceCopy;// ...

  4. Python笔记21-------浅复制和深复制、赋值

    上面图表示浅复制和深复制,针对顶层对象来说,赋值为引用,浅复制和深复制都是复制一个新的对象. 针对子对象来说,浅复制为引用.深复制就是复制两个一样的. 1.赋值 A= [ 1,2,3, [ 'a',' ...

  5. 也来谈一谈js的浅复制和深复制

    1.浅复制VS深复制 本文中的复制也可以称为拷贝,在本文中认为复制和拷贝是相同的意思.另外,本文只讨论js中复杂数据类型的复制问题(Object,Array等),不讨论基本数据类型(null,unde ...

  6. js的浅复制和深复制

    1.浅复制VS深复制 本文中的复制也可以称为拷贝,在本文中认为复制和拷贝是相同的意思.另外,本文只讨论js中复杂数据类型的复制问题(Object,Array等),不讨论基本数据类型(null,unde ...

  7. iOS 浅复制和深复制的深层理解,含示例

    转载:https://www.zybuluo.com/MicroCai/note/50592 版权归 @MicroCai 所有 以下是正文: 浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 ( ...

  8. java基础-浅复制与深复制的理解

    浅复制与深复制在很多编程语言中都有出现,那么什么是浅复制,什么是深复制呢? 要区分浅复制与深复制,首先我们要明确什么是复制,怎样才算是复制.复制的例子在生活中也随处可见,如复印一份文档,复制一段文字等 ...

  9. 深度解析javascript中的浅复制和深复制

    原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null ...

随机推荐

  1. jmeter+maven+jenkins自动化接口测试(下)

    maven+jmeter已经写好了,可以通过maven来执行jmeter的接口测试脚本,怎样实现定时执行测试并发送报告邮件就需要通过jenkins了(jmeter或者testng也可以结合不同的邮件j ...

  2. 【莫烦Pytorch】【P1】人工神经网络VS. 生物神经网络

    滴:转载引用请注明哦[握爪] https://www.cnblogs.com/zyrb/p/9700343.html 莫烦教程是一个免费的机器学习(不限于)的学习教程,幽默风俗的语言让我们这些刚刚起步 ...

  3. 【Network】优化问题——Label Smoothing

    滴:转载引用请注明哦[握爪]https://www.cnblogs.com/zyrb/p/9699168.html 今天来进行讨论深度学习中的一种优化方法Label smoothing Regular ...

  4. Istio

    什么是Istio Istio是Service Mesh(服务网格)的主流实现方案.该方案降低了与微服务架构相关的复杂性,并提供了负载均衡.服务发现.流量管理.断路器.监控.故障注入和智能路由等功能特性 ...

  5. 十行代码分清Java 的 || 和 &&

    发现有些同学到现在还没分不清 || 和 &&的作用 package System; /** * * @ClassName: RandomTest * @Description: 十行代 ...

  6. head里两个重要标签base和meta

    base标签 <base href="../"> 我们并不常用的一个标签,但是一旦用得不当会带来灾难性的影响. 它会影响到所有页面上的href和src属性相对路劲的定位 ...

  7. Apache Hadoop 2.9.2 的HDFS High Available模式部署

    Apache Hadoop 2.9.2 的HDFS High Available 模式部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们知道,当NameNode进程挂掉后,可 ...

  8. Tomcat系列(8)——Tomcat运行模式连接数和线程池

    Connector的主要功能,是接收连接请求,创建Request和Response对象用于和请求端交换数据:然后分配线程让Engine(也就是Servlet容器)来处理这个请求,并把产生的Reques ...

  9. springboot集成freemarker静态资源无法访问

    如题配置文件加上 #设定静态文件路径,js,css等.static为你放置静态资源的文件夹名称,也可以叫别的名字.properties加上 spring.mvc.static-path-pattern ...

  10. sql 查询某个条件多条数据中最新的一条数据或最老的一条数据

    sql 查询某个条件下多条数据中最新的一条数据或最老的一条数据 test_user表结构如下: 需求:查询李四.王五.李二创建的最初时间或者最新时间 1:查询最初的创建时间: SELECT * FRO ...