python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > python浅复制与深复制

python中浅复制copy与深复制deepcopy

作者:鬼圣

本文主要介绍了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浅复制与深复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文