python学习 - copy模块的浅复制(copy)与深复制(deepcopy)

  • 简介
  • copy.copy()详解
  • 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模块的浅复制(copy)与深复制(deepcopy)相关推荐

  1. 小猪的Python学习之旅 —— 15.浅尝Python数据分析

    小猪的Python学习之旅 -- 15.浅尝Python数据分析:分析2018政府工作报告中的高频词 标签:Python 一句话概括本文: 爬取2018政府工作报告,通过jieba库进行分词后做词频统 ...

  2. Python学习--Selenium模块

    1. Python学习--Selenium模块介绍(1) 2.Python学习--Selenium模块学习(2) 其他: 1. Python学习--打码平台 转载于:https://www.cnblo ...

  3. 【Python】Python学习----第一模块笔记

    1.python是什么? python是动态解释型的强类型定义语言. python官方版本的解释器是CPython.该解释器使用C语言开发. 当前主要使用3.x版本的python. 2.第一个pyth ...

  4. Python学习:模块

    本文来自:入门指南 开胃菜参考:开胃菜 使用Python解释器:使用Python解释器 本文对Python的简介:Python简介 Python流程介绍:深入Python流程 Python数据结构:P ...

  5. Python学习 - 常用模块(二)

    目录 一. 常用模块 - hashlib 二. 常用模块 - hmac 三. 常用模块 - logging 四. 常用模块 - re 五. 常用模块 - requests 六. 常用模块 - para ...

  6. python学习第一模块练习

    #!/usr/bin/python# -*- coding:utf-8 -*- ### 第一套题# # 1. 分别解释"=","==","+=&quo ...

  7. python学习 第一模块习题总结

    part1 习题 简述编译型与解释型语言的区别,且分别列出你知道的哪些语言属于编译型,哪些属于解释型? Pyhton 单行注释和多行注释分别用什么? 布尔值分别有什么? 如何查看变量在内存中的地址? ...

  8. Python学习笔记-模块介绍

    (一)-模块概念和基本使用 python是由一系列的模块组成的,每个模块就是一个py为后缀的文件,同时模块也是一个命名空间,从而避免了变量名称冲突的问题.模块我们就可以理解为lib库,如果需要使用某个 ...

  9. 大智慧数据文件python_马克的Python学习笔记#模块和包 3

    让目录或者zip文件成为可以运行的脚本 我们的程序已经从一个简单的脚本进化为一个涉及多个文件的应用.我们希望能有某种简单的方式来让用户运行这个程序 如果应用程序已经进化为由多个文件组成的"庞 ...

最新文章

  1. Delphi的实数计算结果中只保留2位小数
  2. 深入理解Java内存模型--转载
  3. 【mongodb系统学习之六】mongodb配置文件方式启动
  4. iPhone应用程序编程指南(窗口和视图)
  5. Logistic回归与梯度下降法
  6. 福建计算机及应用专业的大学,33所福建大学公布国家级/省级一流本科专业!
  7. hystrix源码小贴士之中断
  8. java 二进制输入_把从键盘输入的一个二进制数赋给变量A 然后如何转换为其他进制...
  9. JUC中的原子类总结
  10. R语言大作业(四):上海市、东京 1997-2018 年GDP值分析
  11. 斯皮尔曼相关系数范围_斯皮尔曼相关系数
  12. 计算机专业毕设一般写什么,计算机专业毕设主要流程
  13. 记一次破解blob加密视频网站的过程
  14. 小名的开源项目【EamonVenti】0.0篇 —— 学习如何搭建一个简单的SpringCloud架构,体验微服务的强大!
  15. matlab plot bo,Matlab的plot~各种颜色和线形
  16. [乡土民间故事_徐苟三传奇]第四一回_放牛娃巧娶富家女
  17. 洞见科技解决方案总监薛婧:联邦学习助力数据要素安全流通
  18. 怎样用好CorelDRAW中的位图颜色遮罩
  19. python如何连redis_python连接redis的方法
  20. AI|优必选称准备IPO 此前公司机器人曾登上春晚舞台

热门文章

  1. 黑马程序员 C++ 基础语法入门 学习记录
  2. 安全风险管控系统服务器地址,某铁路局安全风险管控平台IBM小型机和存储的GPFS方案...
  3. 这个双十一,小米手机销量为何不给力?
  4. Concis组件库封装——LazyLoad懒加载
  5. sqlrelay php,php用sqlrelay 怎么连接oracle
  6. 关于美团:零基础搭建获利的美团饿了么优惠券CPS小程序附源码
  7. 计算机二级ms公共课知识点,考证必学 | 计算机二级MS Office考试全攻略
  8. pc弹窗宽度_PC端网页尺寸设计一
  9. 巾帼绽芬芳 一起向未来(下篇)
  10. Window 10 使用WSL2下载编译Android 10 系统源码,并用sourceInsight 4 看系统源码