概述

Python的列表可以复制,但是这里面有浅复制和深复制,我相信有些人不明白什么是深复制和浅复制,今天我们就来谈谈。

= 号复制

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: rex.cheny@outlook.com list1 = ["A", "B"] list2 = list1 print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
list2.append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

通过在list2中添加一个元素,查看运行结果发现两个列表都变化了。 所以 = 号是列表最简单的复制,其实不能算复制,因为你看两个列表的ID相同。

列表函数copy()复制

下面我们换一种复制方式

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: rex.cheny@outlook.com list1 = ["A", "B"] list2 = list1.copy() print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
list2.append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

这里才是拷贝是真的复制了,因为它们的ID不同。查看运行结果发现只有list2发生变化,但它是浅拷贝。

[:]复制

我们再看另外一种复制方式。其实严格上说切片不是复制,列表切片后会返回新列表,原列表不变。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: rex.cheny@outlook.com list1 = ["A", "B"] list2 = list1[:] print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
list2.append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

运行结果和上面一样

上面演示了3个实例,但是属于浅拷贝的只有第2种复制方式,你可能问,都已经真的拷贝了那怎么还有深复制呢?

列表结构变化演示

这里我们依然使用copy函数,这个函数和使用[:]是一样的,下面有2处变化

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: rex.cheny@outlook.com # 在列表中添加一个列表元素
list1 = ["A", "B", [1, 2]] list2 = list1[:] print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
# 这里我们修改列表中的列表,对内层列表进行修改
list2[2].append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

查看运行结果,你发现内层列表都修改了。你没看错。继续向下看。

那如果在这种列表嵌套的场景中也真的复制成独立互不干涉的怎么办呢?这就用到深复制。

deepcopy函数

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: rex.cheny@outlook.com # 导入该模块
import copy # 在列表中添加一个列表元素
list1 = ["A", "B", [1, 2]] # 深复制
list2 = copy.deepcopy(list1) print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
# 这里我们修改列表中的列表,对内层列表进行修改
list2[2].append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

查看运行结果,符合预期。

什么是浅复制和深复制以及两者区别是什么

其实从效果上看你应该以及明白了两者区别,但要说这个问题就要说数据类型,数据类型分两类:

  • 基本数据类型,包括字符串、数字、布尔。存储的是真实数据。
  • 对象数据类型(引用数据类型),就是对象,类的实例,存储的是对象的引用。

赋值语句 = 意味着什么呢?比如 name = "tom" 赋值语句(=)的作用就是将变量名和一个内存对象进行绑定,如果对象存在就直接绑定,如果不存在就先创建在绑定。name保存的是指向"tom"的指针,而存储tom的内存区域存储的就是tom这个真实数据;list1 = [1, 2] 这种list1存储的是列表对象的指针,但是列表对象本身并不存储数据而是对其他对象的引用,这里的列表包含1和2两个对象,这两个对象是在内存真实存在的,列表对象只是说引用了这些对象而已,列表也仅仅是一种数据的组织形式。

浅复制:复制指针指向,数据在内存中还只是一份,但是只复制一级对象,如果再有一个引用数据类型就不行了

深复制:可以理解为递归浅复制

如果还不明白就看下面的图

下图是使用深度拷贝后的图示

总结

要想生成两个互不干涉的列表就用deepcopy,其他情况任选。

Python列表的深浅复制的更多相关文章

  1. day07 python列表 集合 深浅拷贝

    day07 python   一.知识点补充     1."".join() s = "".join(('1','2','3','4','5'))  #将字符串 ...

  2. Python 列表切片陷阱:引用、复制与深复制

    Python 列表的切片和赋值操作很基础,之前也遇到过一些坑,以为自己很懂了.但今天刷 Codewars 时发现了一个更大的坑,故在此记录. Python 列表赋值:复制"值"还是 ...

  3. Python基础之列表深浅复制和列表推导式

    一.列表深浅复制: 浅拷贝内存图如下: 深拷贝内存图如下: 二.列表推导式: 实例: """ 列表推导式 练习:exercise01 """ ...

  4. Python 字符串拼接、格式化输出、深浅复制

    拼接:"+"号(同类型可拼接) >>>li = [1,2] >>>li + li [1,2,1,2] >>>li*2 [1,2 ...

  5. python 深浅复制与指针内存

    Python是一门非常好的语言,他的长处在于拥有巨大灵活性的同一时候也拥有无比的严谨性,其它语言规定了非常多语法.告诉你什么情况下,语法就是这种,而Python却用非常少的规定,延伸出非常多语法,有些 ...

  6. python基础学习之深浅复制的概念

    1.深浅复制 浅复制,python自带,深复制需要导入模块包 import copy 使用深浅复制,根据id不同写出他们的区别a = [1,2,3]b = [6,7,8]s1 = [a,b]print ...

  7. Python 列表复制

    Python 列表复制 关于Python 列表的复制,有多种方法,常用的 有 赋值.切片.list.copy,copy.deepcopy等. 但是 实际用时 又有区别,不小心可能就用错了. 接下来 简 ...

  8. 【Python初级】由判定回文数想到的,关于深浅复制,以及字符串反转的问题

    尝试用Python实现可以说是一个很经典的问题,判断回文数. 让我们再来看看回文数是怎么定义的: 回数是指从左向右读和从右向左读都是一样的数,例如1,121,909,666等 解决这个问题的思路,可以 ...

  9. python基础知识03-格式化输出和深浅复制

    VIM中HJKL可以上下左右移动光标. 格式化输出和深浅复制 1.字符串的拼接和格式化 sudo pip3 install ipython 安装 ipython 进入 字符串相加 str1 + str ...

随机推荐

  1. Oracle事务与锁 知识点摘记

    事务:事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功要么全部失败. 说明:一组SQL,一个逻辑工作单位,执行整体修改或者整体回退. 事务的相关概念: 1.事务的提 ...

  2. 微信JS SDK接入的几点注意事项

    微信JS SDK接入,主要可以先参考官网说明文档,总结起来有几个步骤: 1.绑定域名:先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”.备注:登录后可在“开发者中心”查看对 ...

  3. 可道云kodexplorer网盘未清理造成linux服务器爆满的解决方法

    今天登陆宝塔面板的时候发现硬盘占用37GB,已经变红提示我空间不足了,惊呆了, 还以为是宝塔抽风了,去远程连接服务器看了一下,懵逼了. df -h 查看挂载目录使用情况 还是不相信现实的我又重启了一下 ...

  4. django 源码报错

    启动django ,一直提示一个 AttributeError: 'str' object has no attribute 'decode' 哥,查了一下午google,就怕是自己判断错了,最后在一 ...

  5. Nginx的虚拟主机配置

    虚拟主机技术能够让同一台服务器.同一组Nginx进程上运行多个网站,降低了资金和服务器资源的损耗.Nginx可以配置三种类型的虚拟主机,本文就是主要介绍这三种虚拟主机配置方式. 配置基于IP的虚拟主机 ...

  6. 【记录】Windows 操作系统常用快捷命令

    https://www.lifewire.com/command-line-commands-for-control-panel-applets-2626060 打印机      control pr ...

  7. SQL 注入检查

    SQLiScanner      简介 叕一款基于SQLMAP和Charles的SQL 注入漏洞扫描工具 支持 Har 文件的扫描(搭配 Charles 使用: Tools=>Auto Save ...

  8. php7安装php-redis扩展

    注:操作系统10.13.3 版本,其他版本的Mac系统应该也是可以的 先安装 按照顺序在命令行执行下面命令,如果当前用户权限不够的话,执行命令加上 sudo cd /usr/local/Cellar ...

  9. framework7 入门(数据获取和传递)

    数据获取 framework7自带request方法 , var app = new Framework7({...});app.request(parameters) 或者 Framework7.r ...

  10. .NET Standard 2.0正式发布了

    亦可赛艇 前天(2017年8月14日),.NET Standard 2.0正式版终于发布了,与之相配套的.NET Core 2.0也同时正式发布,真是令人振奋. 详情请看:https://blogs. ...