Python中list的复制及深拷贝与浅拷贝探究

  在Python中,经常要对一个list进行复制。对于复制,自然的就有深拷贝与浅拷贝问题。深拷贝与浅拷贝的区别在于,当从原本的list复制出新的list之后,修改其中的任意一个是否会对另一个造成影响,即这两个list在内存中是否储存在同一个区域,这也是区分深拷贝与浅拷贝的重要依据。接下来我们就针对Python中list复制的几种方法,来探究一下其是属于深拷贝还是浅拷贝。弄清楚这个问题,有助于我们在编程中规避错误,减少不必要的调试时间。

一、非拷贝方法——直接赋值

  如果用=直接赋值,是非拷贝方法。这两个列表是等价的,修改其中任何一个列表都会影响到另一个列表。这也是Python作为动态语言与C这类静态语言在思想上的不同之处。

 1 #!/usr/bin/env python3
 2 # -*- coding: utf-8 -*-
 3
 4 old = [1, [1, 2, 3], 3]
 5 new = old
 6 print(‘Before:‘)
 7 print(old)
 8 print(new)
 9 new[0] = 3
10 new[1][0] = 3
11 print(‘After:‘)
12 print(old)
13 print(new)

运行结果:

二、浅拷贝的几种方法

1.copy()方法

  我们来看以下代码:

 1 #!/usr/bin/env python3
 2 # -*- coding: utf-8 -*-
 3
 4 old = [1, [1, 2, 3], 3]
 5 new = old.copy()
 6 print(‘Before:‘)
 7 print(old)
 8 print(new)
 9 new[0] = 3
10 new[1][0] = 3
11 print(‘After:‘)
12 print(old)
13 print(new)

运行结果:

  对于list的第一层,是实现了深拷贝,但对于嵌套的list,仍然是浅拷贝。这其实很好理解,内层的list保存的是地址,复制过去的时候是把地址复制过去了。嵌套的list在内存中指向的还是同一个。

2.使用列表生成式

  使用列表生成式产生新列表也是一个浅拷贝方法,只对第一层实现深拷贝。

 1 #!/usr/bin/env python3
 2 # -*- coding: utf-8 -*-
 3
 4 old = [1, [1, 2, 3], 3]
 5 new = [i for i in old]
 6 print(‘Before:‘)
 7 print(old)
 8 print(new)
 9 new[0] = 3
10 new[1][0] = 3
11 print(‘After:‘)
12 print(old)
13 print(new)

运行结果:

3.用for循环遍历

  通过for循环遍历,将元素一个个添加到新列表中。这也是一个浅拷贝方法,只对第一层实现深拷贝。

 1 #!/usr/bin/env python3
 2 # -*- coding: utf-8 -*-
 3
 4 old = [1, [1, 2, 3], 3]
 5 new = []
 6 for i in range(len(old)):
 7     new.append(old[i])
 8 print(‘Before:‘)
 9 print(old)
10 print(new)
11 new[0] = 3
12 new[1][0] = 3
13 print(‘After:‘)
14 print(old)
15 print(new)

运行结果:

4.使用切片

  通过使用[:]切片,可以浅拷贝整个列表。同样的,只对第一层实现深拷贝。

 1 #!/usr/bin/env python3
 2 # -*- coding: utf-8 -*-
 3
 4 old = [1, [1, 2, 3], 3]
 5 new = old[:]
 6 print(‘Before:‘)
 7 print(old)
 8 print(new)
 9 new[0] = 3
10 new[1][0] = 3
11 print(‘After:‘)
12 print(old)
13 print(new)

运行结果:

三、深拷贝的实现

  如果用deepcopy()方法,则无论多少层,无论怎样的形式,得到的新列表都是和原来无关的,这是最安全最清爽最有效的方法。

  使用时,要导入copy。

 1 #!/usr/bin/env python3
 2 # -*- coding: utf-8 -*-
 3
 4 import copy
 5
 6 old = [1, [1, 2, 3], 3]
 7 new = copy.deepcopy(old)
 8 print(‘Before:‘)
 9 print(old)
10 print(new)
11 new[0] = 3
12 new[1][0] = 3
13 print(‘After:‘)
14 print(old)
15 print(new)

运行结果:

  以上,就是对list的复制及深拷贝与浅拷贝探究。鉴于本人水平有限,文中有不妥之处,还请在评论中指出。

原文地址:https://www.cnblogs.com/Bil369/p/9575659.html

时间: 2024-10-31 00:35:01

Python中list的复制及深拷贝与浅拷贝探究的相关文章

Python学习教程:Python列表赋值,复制,深拷贝及5种浅拷贝详解

Python学习教程:Python列表赋值,复制,深拷贝及5种浅拷贝详解 概述 在列表复制这个问题,看似简单的复制却有着许多的学问,尤其是对新手来说,理所当然的事情却并不如意,比如列表的赋值.复制.浅拷贝.深拷贝等绕口的名词到底有什么区别和作用呢? 列表赋值 # 定义一个新列表l1 = [1, 2, 3, 4, 5]# 对l2赋值l2 = l1print(l1)l2[0] = 100print(l1) 示例结果: [1, 2, 3, 4, 5][100, 2, 3, 4, 5] 可以看到,更改赋

python中文件的复制

python中文件的复制 python的os模块有很多文件目录相关的函数,但没有提供直接复制文件的函数,当然可以通过边都边写的方式复制文件.想要直接复制文件可以通过shutil模块 shutil模块是另一个文件,目录的管理接口,提供了一些用于复制文件,目录的函数.copyfile()函数可以实现文件的拷贝,声明如下: import shutil copyfile(src, des) 文件的剪切可以使用move()函数模拟,声明如下: move(src,des) 功能:移动一个文件或者目录到指定的

Python中复制、深拷贝和浅拷贝的区别

深拷贝定义(deepcopy) 在Python中,由于一切皆对象,所以任何变量都可以被引用,也即可以被赋值给任何变量.但是在Python中,给变量赋值,是区分的,一般情况下,Python中的变量赋值都是浅拷贝,如果需要使用深拷贝,需要特别指定. 深拷贝是对原对象的"复制以及粘贴",其实就是在内存中重新开辟了一个新的内存空间来存放这一份数据,两个变量其实是两个不一样的变量,仅仅是数据值相同而已,对两个变量的操作不会相互影响. 浅拷贝(copy) 在Python中进行数据的浅拷贝时,如果此

Python中的赋值(复制)、浅拷贝与深拷贝

https://zhuanlan.zhihu.com/p/54011712 首先需要了解下几个概念 变量:是一个系统表的元素,拥有指向对象的连接空间 对象:被分配的一块内存,存储其所代表的值 引用:是自动形成的从变量到对象的指针 类型:属于对象,而非变量 不可变对象:一旦创建就不可修改的对象,包括字符串.元组.数值类型 (该对象所指向的内存中的值不能被改变.当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址.) 可变对象:

Python的复制,深拷贝和浅拷贝的区别

在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,['a','b']] (1)直接赋值,传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变 >>> alist=[1,2,3,['a','b']] >>> b=alist >>> print b [1, 2, 3, ['a', 'b']] >&g

JAVA中对象的克隆及深拷贝和浅拷贝

使用场景: 在日常的编程过程 中,经常会遇到,有一个对象OA,在某一时间点OA中已经包含了一些有效值 ,此时可能会需一个和OA完全相对的新对象OB,并且要在后面的操作中对OB的任何改动都不会影响到OA的值,也就是OA与Ob是需要完全两个独立的对象. 但OB的初始值是由对象OA确定的.在JAVA语言中,用普通的赋值语句是满足不了需求的.使用对象的clone()方法是实现克隆的最简单.也是最高效的手段. Java的所有类都默认继承java.lang.Object类,在java.lang.Object

流畅的python学习笔记第八章:深拷贝,浅拷贝,可变参数

首先来看赋值,浅拷贝,深拷贝. 一赋值: a=['word',2,3] b=a print id(a),id(b) print [id(x) for x in a] print [id(x) for x in b] a[0]='hello' print a print b E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter8.py 24709080 24709080 [24410496, 21298404, 21298392] [

python(6)——循环删除list、深拷贝和浅拷贝

 列表的内存自动管理功能,在删除列表中的元素时,python会自动对列表内存进行收缩,并移动列表中的元素以保证元素之间没有间隙,所以使用       "循环+remove()方法"来删除列表中元素时会出现元素错位 #删除list1中的奇数 ist1=[1,1,1,2,3,4,5] for i in list1: if i%2!=0: list1.remove(i) print(list1) #[1,2,4] 若要正确循环删list中的元素,定义两个相同的list.一个list用于循环,

Cpp下的深拷贝与浅拷贝探究

下面,通过代码来说说C++中的深浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Name { public: Name(const char*myp){ m_len = strlen(myp); mp = (char*)malloc(m_len + 1); strcpy(mp, myp); } ~Name(){ if (mp != NULL) { free(mp); mp = N