python中浅复制copy与深复制deepcopy

 更新时间:2023年07月20日 10:14:11   作者:鬼圣  
本文主要介绍了python中浅复制copy与深复制deepcopy,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

简介

在使用列表或者字典进行传递参数的时候,可能会遇到函数改变了列表的值,但是不希望印象原来列表中的值,所以,python提供了copy模块,其中包含copy()和deepcopy()两函数,顾名思义copy()指的就是浅复制,deepcopy()指的就是深复制。

copy.copy()详解

copy.copy()主要是用来复制一维列表或者一维元组,即 像[‘A’,‘B’,‘C’,‘D’]这种,如果列表中再套列表,比如这种[‘A’,‘B’,[‘d’,‘e’,‘f’],‘C’] 就不能进行复制更改。下面来做一个简单的测试。

import copy
lis_A = ['A','B','C','D']
lis_B = ['A','B',['d','e','f'],'C']
# 使用copy.copy()复制lis_A
copy_A = copy.copy(lis_A)
print('lis_A的值',  lis_A)
print('copy_A的值', copy_A)
# 打印出lis_A和copy_A的ID值
print('lis_A的ID值',  id(lis_A))
print('copy_A的ID值', id(copy_A))

输出结果是:

lis_A的值 ['A', 'B', 'C', 'D']
copy_A的值 ['A', 'B', 'C', 'D']
lis_A的ID值 1347357010368
copy_A的ID值 1347357613888

这里可以看出。copy_A的值与lis_A的值是一样的,但是它们的ID值是不一样的,说明copy_A指向了一个独立的列表。那么改变copy_A的值是不会去影响lis_A的列表的值,可以做试验:

从上面可以看出,我改变了copy_A中的 ‘B’ 的值,但是并没有影响到lis_A中的值。

使用copy()复制嵌套列表会是什么结果呢?

lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
# 使用copy_B复制 lis_B
copy_B = copy.copy(lis_B)
# 分别打印lis_B和copy_B的值
print('lis_B的值',  lis_B)
print('copy_B的值', copy_B)
# 打印出lis_B和copy_B的ID值
print('lis_B的ID值',  id(lis_B))
print('copy_B的ID值', id(copy_B))

输出的结果是:

lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
lis_B的ID值 2116281195712
copy_B的ID值 2116321275968

咦,也复制出来了呀,怎么回事?别急,接着看,我们 改变一下copy_B中的 B 的值试试。

lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
# 使用copy_B复制 lis_B
copy_B = copy.copy(lis_B)
# 改变copy_B中的 B 的值
copy_B[1] = '改变B'
# 分别打印lis_B和copy_B的值
print('lis_B的值',  lis_B)
print('copy_B的值', copy_B)
# 打印出lis_B和copy_B的ID值
print('lis_B的ID值',  id(lis_B))
print('copy_B的ID值', id(copy_B))

输出结果:

lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', '改变B', ['d', 'e', 'f'], 'C']
lis_B的ID值 2258614705408
copy_B的ID值 2258654720640

从上可以看出,copy_B中B的值已经被改变了,怎么回事?要翻车了吗?我们再改变一下copy_B中的的整个列表试试?

lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
# 使用copy_B复制 lis_B
copy_B = copy.copy(lis_B)
# # 改变copy_B中的 B 的值
# copy_B[1] = '改变B'
# 改变lis_B中嵌套的列表 试试?
copy_B[2] = ['1', '2', '3']
# 分别打印lis_B和copy_B的值
print('lis_B的值', lis_B)
print('copy_B的值', copy_B)
# 打印出lis_B和copy_B的ID值
print('lis_B的ID值', id(lis_B))
print('copy_B的ID值', id(copy_B))

输出的结果是:

lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', 'B', ['1', '2', '3'], 'C']
lis_B的ID值 1860576959872
copy_B的ID值 1860618301312

copy_B的列表也变了。在改变一下copy_B嵌套列表 [‘1’, ‘2’, ‘3’] 中的‘2’的值呢?

lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
# 使用copy_B复制 lis_B
copy_B = copy.copy(lis_B)
# # 改变copy_B中的 B 的值
# copy_B[1] = '改变B'
# 改变lis_B中嵌套的列表 试试?
copy_B[2] = ['1', '2', '3']
# 改变lis_B中嵌套的列表中的值 试试?
copy_B[2][1] = '改变2'
# 分别打印lis_B和copy_B的值
print('lis_B的值', lis_B)
print('copy_B的值', copy_B)
# 打印出lis_B和copy_B的ID值
print('lis_B的ID值', id(lis_B))
print('copy_B的ID值', id(copy_B))

输出结果:

lis_B的值 ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B的值 ['A', 'B', ['1', '改变2', '3'], 'C']
lis_B的ID值 2763457256768
copy_B的ID值 2763497140352

啊,‘2’也改变了,没有影响lis_B的值,怎么回事啊,翻车了吗?我们直接改变复制出来的copy_B的嵌套列表的值,不先改变嵌套列表试试呢。

lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
# 使用copy_B复制 lis_B
copy_B = copy.copy(lis_B)
# # 改变copy_B中的 B 的值
# copy_B[1] = '改变B'
# # 改变lis_B中嵌套的列表 试试?
# copy_B[2] = ['1', '2', '3']
# # 改变lis_B中嵌套的列表中的值 试试?
# copy_B[2][1] = '改变2'
# 直接改变copy_B的值,将上两步注释掉,此时copy_B = lis_B = ['A', 'B', ['d', 'e', 'f'], 'C']
copy_B[2][1] = '改变2'  # 改变2 是改变 ['A', 'B', ['d', 'e', 'f'], 'C'] 中的 e
# 分别打印lis_B和copy_B的值
print('lis_B的值', lis_B)
print('copy_B的值', copy_B)
# 打印出lis_B和copy_B的ID值
print('lis_B的ID值', id(lis_B))
print('copy_B的ID值', id(copy_B))

输出结果:

lis_B的值 ['A', 'B', ['d', '改变2', 'f'], 'C']
copy_B的值 ['A', 'B', ['d', '改变2', 'f'], 'C']
lis_B的ID值 2342836779328
copy_B的ID值 2342878850496

神奇的一幕发生了,改变的是copy_B中的e的值,但是lis_B中e的值也发生了改变。

看懂了吗?这就是使用copy.copy()复制嵌套列表的弊端,表面看复制了lis_B[但是有没有完全复制 lis_B ,这种情况就要使用deepcopy()来进行复制。

但是,为什么之前的情况.为什么能将嵌套列表[‘d’, ‘e’, ‘f’]改为[‘1’, ‘2’, ‘3’],再将[‘1’, ‘2’, ‘3’]的 ‘2’ 变为 ‘改变2’呢。

(1)为什么能将 [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’]?

简单理解,在整体改变[‘d’, ‘e’, ‘f’] 可以把他看做为一个整体,由X来代替,[‘1’, ‘2’, ‘3’]由Y来代替。所以此时的变更相当于把[‘A’, ‘B’, X, ‘C’] 变更为 [‘A’, ‘B’, Y, ‘C’]。实际上变更的还是一维列表。copy.copy()是可以复制一维列表的。

(2)为什么 copy_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’],再去变[‘1’, ‘2’, ‘3’]中的‘2’时,不会影响lis_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’]?

原因是第一步将 copy_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’] 此时已经产生了一个新的列表 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], ‘C’] ,与列表 lis_B = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], ‘C’] 是两个完全不相同的两个列表。自然不回影响。

如果说有个列表 lis_C = [‘A’, ‘B’, [‘d’, ‘e’, ‘f’], [‘x’,‘y’]],先变为 [‘A’, ‘B’, [‘1’, ‘2’, ‘3’], [‘x’,‘y’]],再去改变 'x’变会对源列表产生影响

# 定义一个lis_C
lis_C = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']]
# 复制一个 copy_C
copy_C = copy.copy(lis_C)
# copy_C = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']] 变为 ['A', 'B', ['1', '2', '3'], ['x', 'y']]
copy_C[2] = ['1', '2', '3']
# 在来改变 ['A', 'B', ['1', '2', '3'], ['x', 'y']] 中 'x'的值
copy_C[3][0] = '改变x'
# 分别打印copy_C和copy_C的值
print('lis_C的值', lis_C)
print('copy_C的值', copy_C)
# 打印出lis_C和copy_C的ID值
print('lis_C的ID值', id(lis_C))
print('copy_C的ID值', id(copy_C))

输出结果:

lis_C的值 ['A', 'B', ['d', 'e', 'f'], ['改变x', 'y']]
copy_C的值 ['A', 'B', ['1', '2', '3'], ['改变x', 'y']]
lis_C的ID值 2790729135616
copy_C的ID值 2790729135424

从可以看出,copy_C 中[‘d’, ‘e’, ‘f’] 变成[ ‘1’, ‘2’, ‘3’]时,并不影响lis_C,在 将 [‘x’, ‘y’] 变为 [‘改变x’, ‘y’]时就会印象lis_C

copy.deepcopy()详解

上面说到,在使用copy.copy()复制嵌套的二维列表[‘A’, ‘B’, [‘d’, ‘e’, ‘f’], [‘x’, ‘y’]],然后改变嵌套列表中的值是,会影响到源列表的值,那么使用copy.deepcopy()是否会影响源列表呢?

import copy
# 定义一个lis_D
lis_D = ['A', 'B', ['d', 'e', 'f'], ['x', 'y']]
# 使用deepcopy()复制一个 copy_C
copy_D = copy.deepcopy(lis_D)
# 直接改变 copy_D 中嵌套列表 ['d', 'e', 'f'] 中的值d
copy_D[2][0] = '改变d'
# 分别打印copy_D和copy_D的值
print('lis_D的值', lis_D)
print('copy_D的值', copy_D)
# 打印出lis_D和copy_D的ID值
print('lis_D的ID值', id(lis_D))
print('copy_D的ID值', id(copy_D))

输出结果:

lis_D的值 ['A', 'B', ['d', 'e', 'f'], ['x', 'y']]
copy_D的值 ['A', 'B', ['改变d', 'e', 'f'], ['x', 'y']]
lis_D的ID值 2335362856512
copy_D的ID值 2335362856320

从上述结果可以很明显的看出,使用deepcopy()复制列表lis_之后,直接改变二维列表中的值 d,不会影响到源列表lis_D

到此这篇关于python中浅复制copy与深复制deepcopy的文章就介绍到这了,更多相关python浅复制与深复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python实现寻找最长回文子序列的方法

    python实现寻找最长回文子序列的方法

    这篇文章主要为大家详细介绍了python实现寻找最长回文子序列的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • 使用pandas的box_plot去除异常值

    使用pandas的box_plot去除异常值

    今天小编就为大家分享一篇使用pandas的box_plot去除异常值,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • Python安装图文教程 Pycharm安装教程

    Python安装图文教程 Pycharm安装教程

    这篇文章主要为大家详细介绍了Pycharm及Python安装图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Python Numpy:找到list中的np.nan值方法

    Python Numpy:找到list中的np.nan值方法

    今天小编就为大家分享一篇Python Numpy:找到list中的np.nan值方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • python实现打砖块游戏

    python实现打砖块游戏

    这篇文章主要为大家详细介绍了Python实现打砖块游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • 使用Python在Excel工作表中创建数据透视表的方法

    使用Python在Excel工作表中创建数据透视表的方法

    在数据处理和分析工作中,Excel作为一个广泛使用的工具,提供了强大的功能来管理和解析数据,当面对大量复杂的数据集时,为了更高效地总结、分析和展示数据,创建数据透视表成为一种不可或缺的方法,本文将介绍如何使用Python在Excel工作表中创建数据透视表
    2025-01-01
  • Python进程间通信 multiProcessing Queue队列实现详解

    Python进程间通信 multiProcessing Queue队列实现详解

    这篇文章主要介绍了python进程间通信 mulitiProcessing Queue队列实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Python获取PDF文档的各种页面信息

    Python获取PDF文档的各种页面信息

    了解PDF页面信息对于有效处理、编辑和管理PDF文件至关重要,PDF文件通常包含多个页面,每个页面可能有不同的尺寸、方向、旋转角度以及其他属性,这篇文章将介绍如何使用Python获取PDF文档的各种页面信息,需要的朋友可以参考下
    2025-02-02
  • python中base64加密解密方法实例分析

    python中base64加密解密方法实例分析

    这篇文章主要介绍了python中base64加密解密方法,实例分析了base64加密解密的原理、用途与相关使用技巧,需要的朋友可以参考下
    2015-05-05
  • Python基础学习之条件控制语句小结

    Python基础学习之条件控制语句小结

    如果我需要设置一个死循环,然后靠条件来终止,怎么办?一个很简单的问题,但是我却没有说,这一篇本应该在分支控制语句里面的,现在只能拿出来水文再写一篇了,需要的朋友可以参考下
    2021-05-05

最新评论