详解介绍python 的浅拷贝和深拷贝

copy浅拷贝则是生成新指针的同时,也重新开辟一块内存来放与之前一摸一样的对象实体;
deepcopy深拷贝则是会对对象实体进行递归开辟实体对象的内存空间,也就是一级对象实体中是否有指针指向其他对象。

为了让一个对象发生改变时不对原对象产生副作用,此时,需要一份这个对象的拷贝,python 提供了 copy 机制来完成这样的任务,对应的模块是 copy。

浅拷贝:shadow copy

在 copy 模块中,有 copy 函数可以完成浅拷贝。

from copy import copy

在 python 中,标识一个对象唯一身份的是:对象的id(内存地址),对象类型,对象值,而浅拷贝就是创建一个具有相同类型,相同值但不同id的新对象。

对可变对象而言,对象的值一样可能包含有对其他对象的引用,浅拷贝产生的新对象,虽然具有完全不同的id,但是其值若包含可变对象,这些对象和原始对象中的值包含同样的引用。

>>> import copy
>>> l = {'a': [1,2,3], 'b':[4,5,6]}
>>> c = copy.copy(l)
>>> id(l) == id(c)
False
>>> l['a'].append('4')
>>> c['b'].append('7')
>>> l
{'a': [1, 2, 3, '4'], 'b': [4, 5, 6, '7']}
>>> c
{'a': [1, 2, 3, '4'], 'b': [4, 5, 6, '7']}
>>>

可见浅拷贝产生的新对象中可变对象的值在发生改变时会对原对象的值产生副作用,因为这些值是同一个引用。

浅拷贝仅仅对对象自身创建了一份拷贝,而没有在进一步处理对象中包含的值。因此使用浅拷贝的典型使用场景是:对象自身发生改变的同时需要保持对象中的值完全相同,比如 list 排序。

>>> def sorted_list(olist, key=None):
...     copied_list = copy.copy(olist)
...     copied_list.sort(key=key)
...     return copied_list
...
>>> a = [3,2,1]
>>> b = sorted_list(a)
>>> a
[3, 2, 1]
>>> b
[1, 2, 3]

深拷贝:deep copy

在 copy 模块中,有 deepcopy 函数可以完成深拷贝。

1
from copy import deepcopy
深拷贝不仅仅拷贝了原始对象自身,也对其包含的值进行拷贝,它会递归的查找对象中包含的其他对象的引用,来完成更深层次拷贝。因此,深拷贝产生的副本可以随意修改而不需要担心会引起原始值的改变。

>>> import copy
>>> l = {'a': [1,2,3], 'b':[4,5,6]}
>>> c = copy.deepcopy(l)
>>> id(l) == id(c)
False
>>> l['a'].append('4')
>>> c['b'].append('7')
>>> l
{'a': [1, 2, 3, '4'], 'b': [4, 5, 6]}
>>> c
{'a': [1, 2, 3], 'b': [4, 5, 6, '7']}
>>>

值得注意的是,深拷贝并非完完全全递归查找所有对象,因为一旦对象引用了自身,完全递归可能会导致无限循环。一个对象被拷贝了,python 会对该对象做个标记,如果还有其他需要拷贝的对象引用着该对象,它们的拷贝其实指向的是同一份拷贝

>>> a = [1,2]
>>> b = [a,a]
>>> b
[[1, 2], [1, 2]]
>>> c = deepcopy(b)
>>> id(b[0]) == id(c[0])
False
>>> id(b[0]) == id(b[1])
True
>>> c
[[1, 2], [1, 2]]
>>> c[0].append(3)  #c list 中包含的两份拷贝指向同一处
>>> c
[[1, 2, 3], [1, 2, 3]]
>>>

自定义拷贝机制

使用 _copy_ 和 __deepcopy__ 可以完成对一个对象拷贝的定制。这里不展开了,有机会再探讨自定义拷贝。

时间: 2024-10-30 11:17:59

详解介绍python 的浅拷贝和深拷贝的相关文章

详解在Python和IPython中使用Docker

  这篇文章主要介绍了详解在Python和IPython中使用Docker,Docker是一个吸引人的新系统,可以用来建立有趣的新技术应用,特别是云服务相关的,需要的朋友可以参考下 现在Docker是地球上最炙手可热的项目之一,就意味着人民实际上不仅仅是因为这个才喜欢它. 话虽如此,我非常喜欢使用容器,服务发现以及所有被创造出的新趣的点子和领域来切换工作作为范例. 这个文章中我会简要介绍使用python中的docker-py模块来操作Docker 容器,这里会使用我喜爱的编程工具IPython.

详解rsyslog/Python/LogAnalyzer 记录和查看服务端/客户端日志

RSYSLOG 是一个高效的日志系统,也是目前 Ubuntu 和 CentOS 默认使用的日志系统. LogAnalyzer 是一个 PHP 写成的 Web 前端,使用它可以分析和查看 RSYSLOG 生成的日志. 经过研究,我准备直接使用这两个系统.本文记录了我在配置这两个系统中遇到的问题. rsyslog 配置简介 rsyslog 是负责收集 syslog 的程序,可以用来取代 syslogd 或 syslog-ng. 在这些 syslog 处理程序中,个人认为 rsyslog 是功能最为强

详解使用python crontab设置linux定时任务_python

熟悉linux的朋友应该知道在linux中可以使用crontab设置定时任务.可以通过命令crontab -e编写任务.当然也可以直接写配置文件设置任务. 但是有时候希望通过脚本自动设置,比如我们应用程序部署时等.有需求当然就得想办法解决,不然在程序猿界混(一群自得其乐的猿). 下面进入正题,开始想通过以写文件的形式设置,通过在配置文件中直接追加一行即可.但是读写文件难免有点繁琐,再比如:设置任务时要检查任务是否已经存在:根据输入参数设置相应的任务等.以读写文件难免不太合适.所以想到了"万能&q

Monolog PHP日志类库使用详解介绍

Monolog遵循PSR3的接口规范,可以很轻易的替换成其他遵循同一规范的日志类库.Monolog具有良好的扩展性,通过Handler.Formatter和Processor这几个接口,可以对Monolog类库进行各种扩展和自定义. 基本用法 可以通过github或者composer安装Monolog,以下是使用composer安装最新版本: composer require monolog/monolog 如果您还不了解composer是什么? 请点这里. 要求PHP版本为5.3以上. <?p

MBR和GPT分区表是什么,MBR和GPT分区表详解介绍

MBR和GPT分区表详解 全新硬盘(未初始化)装系统之前,必须对齐进行分区,硬盘分区初始化的格式包括MBR和GPT两种.当然对于基于PowerPC的Mac电脑还有专门的Apple分区图,在这里就不做介绍. MBR的全称是Master Boot Record(主引导记录),MBR早在1983年IBM PC DOS 2.0中就已经提出.之所以叫"主引导记录",是因为它是存在于驱动器开始部分的一个特殊的启动扇区.这个扇区包含了已安装的操作系统的启动加载器和驱动器的逻辑分区信息. 主引导扇区是

MySQL触发器的用途和用法详解介绍

触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力.触发器的作用: 1. 安全性.可以基于数据库的值使用户具有操作数据库的某种权利: 可以基于时间限制用户的操作,例如不允许下班后和节假日修改数据库数据: 可以基于数据库中的数据限制用户的操作,例如不允许股票的价格的升幅一次超过10%. 2. 审计.可以跟踪用户对数据库的操作: 审计用户操作数据库的语句: 把用户对数据库的更新写入审计表. 3. 实现复杂的数据完整性规则:

Nginx 服务器安装及配置文件详解介绍_nginx

Nginx 在工作中已经有好几个环境在使用了,每次都是重新去网上找博客,各种编译配置,今天自己也整理一份安装文档和 nginx.conf 配置选项的说明,留作以后参考. 1. 安装nginx 1.1 选择稳定版本 我们编译安装nginx来定制自己的模块,机器CentOS 6.2 x86_64.首先安装缺少的依赖包: # yum -y install gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre pcre-d

新浪微博OAuth详解以Python为例

让我先吐槽一下新浪微博的那个 OAuth 文档,写得就像个锤子一样! 1. 什么是OAuth OAuth 是一套认证形式,并被逐渐推荐为一套标准,它的老家在 http://oauth.net . OAuth 实现的是一套三方委托认证的模式. 举例来说,有人想知道你新浪微博上的所有粉丝都有哪些,而你也愿意让他知道.但是,这里有一个问题,如果你直接把账号和密码告诉这个人的话,你可能会觉得很不安全,你只想把有限的东西给这个人,而不是把账号和密码都交出来. 于是,可以使用这样的一种方式,这个人去找新浪要

MySQL分库分表的实现过程详解介绍

MySQL分库分表基础表介绍 表基本模型结构 这里我们模拟一个商城的基本的表结.此结构由(用户.门店.导购.门店商品.订单.订单对应的商品).其中,导购也是一个用户,门店是只属于一个店主的,同时店主本身也是一个导购也是一个普通用户. 结构图:   构造数据脚本 MySQL分库分表(1)-脚本 对业务场景进行模拟 场景1:购买者下订单. 1.从session中获得客户ID. 2.可以通过时间戳等拼凑一个订单ID(在创建表的时候为了方便我用自增的,在以下我们一直就吧订单ID看成不是自增的,是用程序生