Shallow Copy Deep Copy in Python list

  今天在写一个小程序的时候用到了2维数组, 顺手就写成了[[0.0]*length]*length, 结果为了这个小错,调试了半个多小时,

其实之前对与浅复制和深复制已经做过学习和总结, 但真正编程用到这些知识时还是掉入了陷阱中. 所以在此做进一步的总结:

  本文通过几个实例来说明Python中list的深复制和浅复制:

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0][0] = 10    #NO WAY
Traceback (most recent call last):File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> a[0].append(1)
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]

  a[0].append(1)后, 如果a的输出结果让你感到有些困惑,你可以参考这里(原因是Python中的*运算采用的是浅复制).

  同样的道理,下面的代码我们应该都能够理解:

>>> a[3].append(9)
>>> a
[[1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9]]
>>> a[2][1] = 3
>>> a
[[1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3]]

  让我们一起来分析一下:

  对于a(理解为一个2维数组)中的每一个元素都是一个list(理解为一个1维数组), 但我们需要注意的是a的每一个元素

a[0],a[1],a[2]...指向的是同一段内存区域(浅复制),所以更改(修改值或添加值)任何一个元素(a[0]或a[1]...a[9])都会直接影

响到其它的元素.

  如何验证a中的每一个元素a[0], a[1],...,a[9]指向同一段内存区域? 可以通过id方法来验证:

>>> id.__doc__
"id(object) -> integer

Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
"

 

>>> a = [[]]*10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> id(a[0])
3071938316L
>>> id(a[1])
3071938316L
>>> a[0].append(1)
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> id(a[0])
3071938316L
>>> id(a[1])
3071938316L
>>> 

注意:虽然a的每一个元素a[0],a[1],a[2]...指向的是同一段内存区域,但a中的各个元素是独立的元素(他们相同但不同一),

也就是说删除掉任何一个数据对其他的数据没有任何影响:

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(1)
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> len(a)
10
>>> del(a[2])
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> len(a)
9

  那么应该怎么实现深复制呢?其实在前面提到的文章中已经介绍了这一方法:  

>>> c = [[] for i in range(10)]
>>> c
[[], [], [], [], [], [], [], [], [], []]
>>> c[0].append(3)
>>> c
[[3], [], [], [], [], [], [], [], [], []]
>>> 

  至此, 我觉得还有一点需要说明:

  一定要理解*操作的对象是谁, 例如: [2]*10得到[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], *10操作的对象是[]中的2, 也就是说*10操

作使list中的元素2复制10次. 同理[[]]*10得到[[], [], [], [], [], [], [], [], [], []],*10操作的对象是[]中的[], 也就是说*10

操作使list中的元素[]浅复制10次, 这10个空list指向内存中相同的区域(参见上面用id验证部分).

  下面用2段代码作为对比列出来, 便于查看:

>>> a = [2] * 10
>>> a
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
>>> id(a[0])
164067492
>>> id(a[1])
164067492
>>> a[0] = 1  #NOTE
>>> id(a[0])  #NOTE
164067504
>>> id(a[1])
164067492
>>> 

 

>>> b = [[]] * 10
>>> b
[[], [], [], [], [], [], [], [], [], []]
>>> id(b[0])
3072965964L
>>> id(b[1])
3072965964L
>>> b[0].append(10)
>>> id(b[0])
3072965964L
>>> id(b[1])
3072965964L
>>> b
[[10], [10], [10], [10], [10], [10], [10], [10], [10], [10]]
>>> b[0][0] = 1
>>> b
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> id(b[0])
3072965964L
>>> id(b[1])
3072965964L
>>> b[0] = [10]
>>> b
[[10], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> id(b[1])
3072965964L
>>> id(b[0])
3072965996L
>>> 

 

转载于:https://www.cnblogs.com/lxw0109/p/shallow-copy-and-deep-copy.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python学习之wxPython

1、成功安装wxPython 2、第一个小图形化界面的小程序—创建并显示一个web小框架 参考http://www.cnblogs.com/fnng/archive/2013/05/23/3094033.html #! /usr/bin/env python#codingutf-8import wxappwx.App()winwx.Frame(None)win.Show()app.MainLoop() 3、运行报错 > &qu…

ssh框架搭建

下载地址&#xff1a;源码和详细搭建步骤 使用myeclipse2014搭建ssh框架1. spring搭建2. struts2搭建3. hibernate搭建4. applicationContext编写5. web.xml编写1. spring搭建 创建一个javaweb项目 导入spring框架 最高版本3.1支持 4. 选择类库 spring导入完毕 2. str…

iOS: 图解Xcode常用的快捷键

对于习惯了Windows 操作的开发者来说&#xff0c; 初次接触Xcode时&#xff0c;你会感到有种种不适&#xff0c;其中一个重要的原因就是&#xff0c; 相比Windows X86 电脑&#xff0c; Mac 多出了两个物理键&#xff1a; Fn 和 Command。 尤其是 Command键&#xff0c;在 Ma…

vue参数传递

目标&#xff1a;纯前端vue实现页面跳转restful传值 目录1. 全局路由配置2. 如何传值3. 页面取值1. 全局路由配置 // 路由器主配置文件 import Vue from vue import VueRouter from vue-routerimport Main from ../views/main import Login from ../views/login// 导入用户模块…

adb——Android的ADB工具使用

一、定义与作用&#xff1a; ADB全称Android Debug Bridge, 就是起到调试桥的作用。是android sdk里的一个工具, 用这个工具可以直接操作管理android模拟器或者真实的andriod设备,默认情况下当我们运行Eclipse时adb进程就会自动运行。当然我们也可以在外部使用本身自带的一些命…

beforeRouteEnter,beforeRouteLeave函数

操作&#xff1a; 是时机函数&#xff0c;在页面加载前&#xff0c;可以在这两个函数里面做一些事情&#xff0c; 比如发送异步请求。 类似过滤器&#xff0c;或者拦截器。1. axios安装 安装报错&#xff0c;多装几遍&#xff0c;或者用cnpm安装 npm install axios -s npm in…

排错“未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配”...

问题&#xff1a;在C#给C传数组类型数据时报此错&#xff0c;相应英文信息为“Type could not be marshaled, because the length of an embed array doesnt not match the declared length in the layout” 原因1、声明的数组长度和实际的数组长度不一致&#xff0c;比如声明的…

a标签的href与onclick中使用js的区别

href与onclick中javascript的区别一般没用到都没注意&#xff0c;但出错时才有些郁闷&#xff0c;看文本章解释如下&#xff1a; 以前一直很随意&#xff0c;后来看.net里的linkbutton似乎是用在<a href"javascript:fun();"...>的形式&#xff0c;今天用这种方…

手把手教你搭建springboot程序

spring-boot项目搭建一、从官网搭建1、进入spring官网&#xff0c;快速初始化一个项目2、填写项目基本信息3、项目结构分析4、添加项目依赖5、下载到本地6、解压7、idea&#xff0c;打开&#xff0c;使用maven构建项目8、使用maven构建9、这是构建好的&#xff0c;其它目录全部…

jquery的鼠标移入移出事件hover、mouseenter、mouseleave、mouseover、mouseout

hover:鼠标进入元素的子元素时不会触发‘鼠标移开’的事件&#xff1b;mouseenter、mouseleave&#xff1a;效果与hover相同&#xff1b;mouseover&#xff1a; 鼠标进入元素和进入它的子元素时都会触发‘mouseover’的事件&#xff0c;即使添加了event.stopPropagation();retu…

yaml格式,给Java类绑定数据

这里写目录标题1、基本语法2、给java bean注入值3、测试1、基本语法 # yaml 配置文件写法&#xff0c;代替properties写法 # 严格区分空格# 内注入到配置类中 server:port: 8081# 对象 student:name: jackage: 3# 行内写法 map student1: {name: jack, age: 3}# array or coll…

android编程常见问题- Resource ID #0x7f070001 type #0x12 is not valid

问题说明&#xff1a; AndroidRuntime(1705): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.activitytest/com.example.activitytest.SecondActivity}: android.content.res.Resources$NotFoundException: Resource ID #0x7f070001 type #…

scm 软件配置管理

目录1、为什么需要使用SCM2、什么是SCM3、作用变更控制&#xff1a;版本控制的内容版本控制策略4、版本控制工具1、为什么需要使用SCM 1. 更改源文件&#xff0c;但不知道哪个是最新的&#xff1b; 2. 我不了解文件的修改过程&#xff0c;尤其是最后修改了哪几行以及为什么修改…

一款纯css3实现的超炫动画背画特效

之前为大家介绍了很多款由纯css3实现的特效。今天要再给大家带来一款纯css3实现的超炫动画背画特效。代码非常简单&#xff0c;没有引用任何其它js代码。css代码也不多。效果非常炫。一起看下效果图&#xff1a; 在线预览 源码下载 实现的代码。 html代码&#xff1a; <di…

springboot指定首页(静态资源导入)

ResourceProperties小小的源码分析1. 静态资源该放在哪里&#xff1f;2. 首页该如何自动展示&#xff1f;1. 静态资源该放在哪里&#xff1f; springboot 集成了spring-webmvc,这个都是知道的。 该框架的特点是自动装配。 先看WebMvcAutoConfiguration自动装配类 public void…

Mybatis日常操作遇到的问题

如果参数是一个基本类型&#xff08;不是一个类对象&#xff09;&#xff0c;在写sql需要对这个基本类型判断时&#xff0c;这个基本类型的名称必须是value,因为mybatis对于单个基本类型而言&#xff0c;默认名称是value&#xff0c;自定义的名称在用于if/when时&#xff0c;代…

log4j日志收集

目录1. log4j 是什么1. 日志管理工具2. 有哪些组成部分&#xff1f;3. 日志级别2. 输出端与日志格式化器Appender&#xff08;输出端&#xff09;Layout&#xff08;日志格式化器&#xff09;3. log4j.properties占位符&#xff0c;格式化日志4. 使用1. log4j 是什么 1. 日志管…

【从零之三(更)】自定义类中调用讯飞语音包错误解决办法

原文&#xff1a;http://blog.csdn.net/monkeyduck/article/details/24302655 在科大讯飞语音包的Mscdemo中它的方法都是写在Activity中的&#xff0c;这样其实并不是很好&#xff0c;因为Activity只是负责UI交互的&#xff0c;如果项目很简单自然可以&#xff0c;但是一旦比较…