Python中list的复制及深拷贝与浅拷贝探究
在Python中,经常要对一个list进行复制。对于复制,自然的就有深拷贝与浅拷贝问题。深拷贝与浅拷贝的区别在于,当从原本的list复制出新的list之后,修改其中的任意一个是否会对另一个造成影响,即这两个list在内存中是否储存在同一个区域,这也是区分深拷贝与浅拷贝的重要依据。接下来我们就针对Python中list复制的几种方法,来探究一下其是属于深拷贝还是浅拷贝。弄清楚这个问题,有助于我们在编程中规避错误,减少不必要的调试时间。
一、非拷贝方法——直接赋值
如果用=直接赋值,是非拷贝方法。这两个列表是等价的,修改其中任何一个列表都会影响到另一个列表。这也是Python作为动态语言与C这类静态语言在思想上的不同之处。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- old = [1, [1, 2, 3], 3]
new = old
print('Before:')
print(old)
print(new)
new[0] = 3
new[1][0] = 3
print('After:')
print(old)
print(new)
运行结果:
二、浅拷贝的几种方法
1.copy()方法
我们来看以下代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*- old = [1, [1, 2, 3], 3]
new = old.copy()
print('Before:')
print(old)
print(new)
new[0] = 3
new[1][0] = 3
print('After:')
print(old)
print(new)
运行结果:
对于list的第一层,是实现了深拷贝,但对于嵌套的list,仍然是浅拷贝。这其实很好理解,内层的list保存的是地址,复制过去的时候是把地址复制过去了。嵌套的list在内存中指向的还是同一个。

2.使用列表生成式
使用列表生成式产生新列表也是一个浅拷贝方法,只对第一层实现深拷贝。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- old = [1, [1, 2, 3], 3]
new = [i for i in old]
print('Before:')
print(old)
print(new)
new[0] = 3
new[1][0] = 3
print('After:')
print(old)
print(new)
运行结果:
3.用for循环遍历
通过for循环遍历,将元素一个个添加到新列表中。这也是一个浅拷贝方法,只对第一层实现深拷贝。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- old = [1, [1, 2, 3], 3]
new = []
for i in range(len(old)):
new.append(old[i])
print('Before:')
print(old)
print(new)
new[0] = 3
new[1][0] = 3
print('After:')
print(old)
print(new)
运行结果:
4.使用切片
通过使用[:]切片,可以浅拷贝整个列表。同样的,只对第一层实现深拷贝。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- old = [1, [1, 2, 3], 3]
new = old[:]
print('Before:')
print(old)
print(new)
new[0] = 3
new[1][0] = 3
print('After:')
print(old)
print(new)
运行结果:
三、深拷贝的实现
如果用deepcopy()方法,则无论多少层,无论怎样的形式,得到的新列表都是和原来无关的,这是最安全最清爽最有效的方法。
使用时,要导入copy。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- import copy old = [1, [1, 2, 3], 3]
new = copy.deepcopy(old)
print('Before:')
print(old)
print(new)
new[0] = 3
new[1][0] = 3
print('After:')
print(old)
print(new)
运行结果:
以上,就是对list的复制及深拷贝与浅拷贝探究。鉴于本人水平有限,文中有不妥之处,还请在评论中指出。
Python中list的复制及深拷贝与浅拷贝探究的更多相关文章
- 浅谈python 复制(深拷贝,浅拷贝)
博客参考:点击这里 python中对象的复制以及浅拷贝,深拷贝是存在差异的,这儿我们主要以可变变量来演示,不可变变量则不存在赋值/拷贝上的问题(下文会有解释),具体差异如下文所示 1.赋值: a=[1 ...
- python中文件的复制
python中文件的复制 python的os模块有很多文件目录相关的函数,但没有提供直接复制文件的函数,当然可以通过边都边写的方式复制文件.想要直接复制文件可以通过shutil模块 shutil模块是 ...
- Python中复制、深拷贝和浅拷贝的区别
深拷贝定义(deepcopy) 在Python中,由于一切皆对象,所以任何变量都可以被引用,也即可以被赋值给任何变量.但是在Python中,给变量赋值,是区分的,一般情况下,Python中的变量赋值都 ...
- [Python]Python中的浅复制与深复制
看python的文档,发现list有copy方法,描述说效果同a[:]. 感觉有点惊讶,之前一直以为a[:]执行的是深复制. test了一下,发现确实如果a中存在可变对象,如list/set/dict ...
- python的复制,深拷贝和浅拷贝的区别
在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,[& ...
- python的复制,深拷贝和浅拷贝的区别(转)
在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,[& ...
- 【转】python的复制,深拷贝和浅拷贝的区别
在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,[& ...
- JAVA中对象的克隆及深拷贝和浅拷贝
使用场景: 在日常的编程过程 中,经常会遇到,有一个对象OA,在某一时间点OA中已经包含了一些有效值 ,此时可能会需一个和OA完全相对的新对象OB,并且要在后面的操作中对OB的任何改动都不会影响到OA ...
- Python中的赋值(复制)、浅拷贝、深拷贝之间的区别
1.赋值: 只是复制了新对象的引用,不会开辟新的内存空间. 2.浅拷贝: 创建新对象,其内容是原对象的引用. 浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数. 如: ...
随机推荐
- sqlserver 新建只读权限用户
1,新建只能访问某一个表的只读用户. --添加只允许访问指定表的用户:execsp_addlogin'用户名','密码','默认数据库名' --添加到数据库execsp_grantdbaccess'用 ...
- 201621123014《JAVA程序设计》第2周学习总结
1. 本周学习总结 引用数据类型:JAVA定义字符串实际上是创建字符串的引用,将引用指向需要的字符串. 字符串常量池:直接对引用赋值时,会先在字符串中搜索是否有这个对象,已有则不创建直接指向它. St ...
- codeforces 655C C. Enduring Exodus(二分)
题目链接: C. Enduring Exodus time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
- Android: 一个两点触控的案例
下面是一个两点触控的案例代码: package com.zzj; import android.app.Activity; import android.os.Bundle; import andro ...
- 通过rtmpdump推送海康视频流到red5服务器
现在主流的网络摄像机都支持标准H264视频格式,例如 海康网络摄像机, 通过海康提供的网络SDK可以获取到视频码流.我测试的这款相机,视频编码采用的是H264,音频编码采用的是G711a. 这里,我仅 ...
- java基础回顾之IO
Java的IO 是Java运用重要部分之一,涉及到的内容也比较多,容易混淆,一段时间不用,可能就会遗忘,要时常回顾记忆一下: (图片来源于网络) Java 流在处理上分为字符流和字节流. 字符流处理的 ...
- android SDK manager 无法获取更新版本列表【转载】
http://mirrors.neusoft.edu.cn/eclipse/releases/luna/打开这个网址就可以看到adt的详细信息: http://developer.android.c ...
- 每天一个linux命令(13):more命令
版权声明更新:2017-05-17博主:LuckyAlan联系:liuwenvip163@163.com声明:吃水不忘挖井人,转载请注明出处! 1 文章介绍 本文介绍了Linux下面的mv命令. 2. ...
- vue2.0中的$router 和 $route的区别
1.router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了 ...
- Puppet master nginx 扩展提升性能(puppet自动化系列4)
puppet使用SSL(https)协议来进行通讯,默认情况下,puppet server端使用基于Ruby的WEBRick HTTP服务器.由于WEBRick HTTP服务器在处理agent端的性能 ...