python——赋值与深浅拷贝
结合python变量存储的特性从内存的角度来谈一谈赋值和深浅拷贝~~~
预备知识一——python的变量及其存储
在详细的了解python中赋值、copy和deepcopy之前,我们还是要花一点时间来了解一下python内存中变量的存储情况。
在高级语言中,变量是对内存及其地址的抽象。对于python而言,python的一切变量都是对象,变量的存储,采用了引用语义的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量的只本身。
引用语义与值语义详解
我们来看一张简单易懂的图理解一下python的引用语义和C语言值语义在内存中的存储情况,左右两个图,分别表示了python中变量存储与C语言中变量存储区别:
预备知识二——各基本数据类型的地址存储及改变情况
在python中的数据类型包括:bool、int、long、float、str、set、list、tuple、dict等等。我们可以大致将这些数据类型归类为简单数据类型和复杂的数据结构。
数据结构及其划分依据
由于python中的变量都是采用的引用语义,数据结构可以包含基础数据类型,导致了在python中数据的存储是下图这种情况,每个变量中都存储了这个变量的地址,而不是值本身;对于复杂的数据结构来说,里面的存储的也只只是每个元素的地址而已。:
1.数据类型重新初始化对python语义引用的影响
变量的每一次初始化,都开辟了一个新的空间,将新内容的地址赋值给变量。对于下图来说,我们重复的给str1赋值,其实在内存中的变化如下右图:
从上图我们可以看出,str1在重复的初始化过程中,是因为str1中存储的元素地址由'hello world'的地址变成了'new hello world'的。
2.数据结构内部元素变化重对python语义引用的影响
对于复杂的数据类型来说,改变其内部的值对于变量的影响:
当对列表中的元素进行一些增删改的操作的时候,是不会影响到lst1列表本身对于整个列表地址的,只会改变其内部元素的地址引用。可是当我们对于一个列表重新初始化(赋值)的时候,就给lst1这个变量重新赋予了一个地址,覆盖了原本列表的地址,这个时候,lst1列表的内存id就发生了改变。上面这个道理用在所有复杂的数据类型中都是一样的。
变量的赋值
搞明白了上面的内容,再来探讨变量的赋值,就变得非常简单了。
1.str的赋值
我们刚刚已经知道,str1的再次初始化(赋值)会导致内存地址的改变,从上图的结果我们可以看出修改了str1之后,被赋值的str2从内存地址到值都没有受到影响。
看内存中的变化,起始的赋值操作让str1和str2变量都存储了‘hello world’所在的地址,重新对str1初始化,使str1中存储的地址发生了改变,指向了新建的值,此时str2变量存储的内存地址并未改变,所以不受影响。
2.复杂的数据结构中的赋值
刚刚我们看了简单数据类型的赋值,现在来看复杂数据结构变化对应内存的影响。
上图对列表的增加修改操作,没有改变列表的内存地址,lst1和lst2都发生了变化。
对照内存图我们不难看出,在列表中添加新值时,列表中又多存储了一个新元素的地址,而列表本身的地址没有变化,所以lst1和lst2的id均没有改变并且都被添加了一个新的元素。
简单的比喻一下,我们出去吃饭,lst1和lst2就像是同桌吃饭的两个人,两个人公用一张桌子,只要桌子不变,桌子上的菜发生了变化两个人是共同感受的。
初识拷贝
我们已经详细了解了变量赋值的过程。对于复杂的数据结构来说,赋值就等于完全共享了资源,一个值的改变会完全被另一个值共享。
然而有的时候,我们偏偏需要将一份数据的原始内容保留一份,再去处理数据,这个时候使用赋值就不够明智了。python为这种需求提供了copy模块。提供了两种主要的copy方法,一种是普通的copy,另一种是deepcopy。我们称前者是浅拷贝,后者为深拷贝。
深浅拷贝一直是所有编程语言的重要知识点,下面我们就从内存的角度来分析一下两者的区别。
浅拷贝
首先,我们来了解一下浅拷贝。浅拷贝:不管多么复杂的数据结构,浅拷贝都只会copy一层。下面就让我们看一张图,来了解一下浅浅拷贝的概念。
看上面两张图,我们加入左图表示的是一个列表sourcelist,sourcelist = ['str1','str2','str3','str4','str5',['str1','str2','str3','str4','str5']];
右图在原有的基础上多出了一个浅拷贝的copylist,copylist = ['str1','str2','str3','str4','str5',['str1','str2','str3','str4','str5']];
sourcelist和copylist表面上看起来一模一样,但是实际上在内存中已经生成了一个新列表,copy了sourceLst,获得了一个新列表,存储了5个字符串和一个列表所在内存的地址。
我们看下面分别对两个列表进行的操作,红色的框框里面是变量初始化,初始化了上面的两个列表;我们可以分别对这两个列表进行操作,例如插入一个值,我们会发现什么呢?如下所示:
从上面的代码我们可以看出,对于sourceLst和copyLst列表添加一个元素,这两个列表好像是独立的一样都分别发生了变化,但是当我修改lst的时候,这两个列表都发生了变化,这是为什么呢?我们就来看一张内存中的变化图:
我们可以知道sourceLst和copyLst列表中都存储了一坨地址,当我们修改了sourceLst1的元素时,相当于用'sourceChange'的地址替换了原来'str1'的地址,所以sourceLst的第一个元素发生了变化。而copyLst还是存储了str1的地址,所以copyLst不会发生改变。
当sourceLst列表发生变化,copyLst中存储的lst内存地址没有改变,所以当lst发生改变的时候,sourceLst和copyLst两个列表就都发生了改变。
这种情况发生在字典套字典、列表套字典、字典套列表,列表套列表,以及各种复杂数据结构的嵌套中,所以当我们的数据类型很复杂的时候,用copy去进行浅拷贝就要非常小心。。。
深拷贝
刚刚我们了解了浅拷贝的意义,但是在写程序的时候,我们就是希望复杂的数据结构之间完全copy一份并且它们之间又没有一毛钱关系,应该怎么办呢?
我们引入一个深拷贝的概念,深拷贝——即python的copy模块提供的另一个deepcopy方法。深拷贝会完全复制原变量相关的所有数据,在内存中生成一套完全一样的内容,在这个过程中我们对这两个变量中的一个进行任意修改都不会影响其他变量。下面我们就来试验一下。
看上面的执行结果,这一次我们不管是对直接对列表进行操作还是对列表内嵌套的其他数据结构操作,都不会产生拷贝的列表受影响的情况。我们再来看看这些变量在内存中的状况:
看了上面的内容,我们就知道了深拷贝的原理。其实深拷贝就是在内存中重新开辟一块空间,不管数据结构多么复杂,只要遇到可能发生改变的数据类型,就重新开辟一块内存空间把内容复制下来,直到最后一层,不再有复杂的数据类型,就保持其原引用。这样,不管数据结构多么的复杂,数据之间的修改都不会相互影响。这就是深拷贝~~~
转载于:https://blog.51cto.com/zhdsql/1944760
相关文章:
【计算机视觉】EmguCV学习笔记(4)分离颜色通道以及多通道图像混合
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

oracle的存储过程调试,oracle 运行普通方式及调试debug方式存储过程性能区别
调试某一存储过程时,在plsql developer debug调试执行时,20多分钟都执行不完,后分析如下:1,查询调试会话运行存储过程的对应sqlselect sid,serial#,event,status,sql_id,prev_sql_id,action,module from v$session where suser12…

关于一个无限分类的多选,单选相关的控件
最近在一个项目中需要用到无限分类的平铺多选,单选这些功能,查了一些资料,结果大都是一些用IFrame这样的东西做的,虽然用起来直观,但本人更喜欢集成控件形式的,于是抽了一些时间做了一个.思路是利用控件JS不同的无限分类表,支持一页多控件,支持不同的无限分类表.效果图如下: 当…

ubuntu如何修改字符集编码
系统支持编码的修改如下:1. 使用如下命令查看系统支持的字符集cat /usr/share/i18n/SUPPORTED说明:查看系统支持的字符集,你需要注意的是支持字符集的格式,如对中文会有以下一些显示(我的系统如此,我不知是…
【怎样写代码】小技巧 -- 关于引用类型的两种转换方式
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

Oracle中的iot_type,oracle IOT表学习
IOT: Index-Organized Table索引组织表含义即将表结构整体放入索引中,且是按照主键进行排序的。创建:create table emp_iot(emp_no int,emp_name varchar2(100),dept_no int,salary number(10,2),constraint pk_empi primary key(emp_no, emp_name, dept…
如何查询并解决80端口 (转)
转自:http://www.cnblogs.com/chaofan/archive/2009/12/02/1615691.html 今天在使用apache的时候80端口被占用了,解决办法如下 在命令行里输入netstat -aon|findstr "80" 查看使用了80端口的tcp pid pid为1564 在任务管理器中将该进程结束掉即…

深证信息等三方拟联合开展大数据研究
昨日,深圳证券信息有限公司(下称“深证信息”)、泛欧交易所、北京新浪互联信息服务有限公司(下称“新浪网”)联合签署了合作备忘录,三方将基于各自优势在互联网大数据应用研究、股票指数开发、跨境指数产品…
【怎样写代码】小技巧 -- 关于方法中修饰形参的关键词
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

oracle schedule stop,Oracle调度Schedule特性(第八部分)-Windows和Window Groups
哈哈,关于schedule的内容还没完,本章讲Windows,通常说的Windows是指盖首富的操作系统,而此处所说的Windows,是指SCHEDULER特性中的一个子项。在SCHEDULER中,WINDOW对应的是一个时间窗口的概念。我们知道普通…
CSS入门-五个简单,但有用的CSS属性
今天说的这5个CSS属性,你可能会很熟悉,但是你可能会很少会去使用.这个教程所讲得不是关于CSS3的属性,而是依旧使用CSS2属性来说明,这些属性广泛的被各种浏览器所支持:clip,min-height,white-space,cursor和display.所以不要错过这个教程,因为你会发现他们是多么的有用.1.CSS Cl…

借助线下渠道逆袭?小米的愿望恐成镜花水月!
小米5的发布,让久未有波澜的中国手机市场又泛起几点涟漪。 而在小米5发布的同时,小米销售方式的改变,也让人眼前一亮。小米,已经由最初的“反传统”,开始向“传统”靠拢了。 小米5发布会上,小米告诉大家&am…
【怎样写代码】函数式编程 -- Lambda表达式(一):引出
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

oracle创建DBA角色命令,oracle常用DBA命令
1.查看用户拥有的数据库对象Sql代码select object_name from user_objects;2.查看约束信息Sql代码select constraint_name from user_constraints;3.查看用户所拥有的表Sql代码select table_name from user_tables;或Sql代码select *from tab;4.查看用户所拥有的视图Sql代码sel…

Ext JS Designer 1.0.5 发布
ExtJS官方Blog上发布了Ext JS Designer新版本,版本号为1.0.5,这个版本添加了不少新特性,如直接修改title,config参数搜索等等。虽然这个版本仍然不支持代码生成,不过另一则文章则让人感觉代码生成的日子也不远了。 此版…
【怎样写代码】函数式编程 -- Lambda表达式(二):C#常用委托
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

前端设计(一)
前端设计(一)

oracle time格式化比较,ORACLE DATE和TIMESTAMP数据类型的比较(二) (转)
ORACLE DATE和TIMESTAMP数据类型的比较(二) (转)[more]原著作者:James KmannTIMESTAMP数据的格式化显示和DATE 数据一样。注意,to_char支持date和timestamp,但是trunc却不支持TIMESTAMP数据类型。这已经清楚表明了在当两个时间的差别极度重要…

模式实例之——外观实例
场景:银行柜员机取钱或存钱描述:从银行的柜员机取了100块钱(一)子系统/// <summary>/// 子系统抽象/// </summary>public interface IDo{void ShowMessage(string strMemo);}(二)各个子系统///…

cnpm install -g generator-gulp-webapp yo gulp-webapp test-gulp-webapp
2019独角兽企业重金招聘Python工程师标准>>> cnpm install -g generator-gulp-webapp yo gulp-webapp test-gulp-webapp 转载于:https://my.oschina.net/yizhichao/blog/1189216
【怎样写代码】函数式编程 -- Lambda表达式(三):LINQ初步
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

oracle触发器初始化,oracle – 触发器无法初始化变量
我有触发审计,它存储了对任何EMP表行执行的操作.这个触发器工作正常,除了在某些情况下(很少发生,我无法确定确切的条件)它给了我Oracle错误:ORA-01400:无法插入NULL(“MY_SCHEMA”.“HIST_EMP”.“操作”)CREATE OR REPLACE TRIGGER HIST_EMP_AIUDAFTER …

翻页导航条页码计算方法
在开发搜索引擎等应用时,提供一个翻页导航条是必须的。我看过网上一些相关的代码,搞得很复杂。晕~~~ 其实其数学计算公式非常简单,本文提供两种最常用的算法。翻页式样式如下。每次显示10个页码,并提供"前十"、"后…

ArcGIS水文分析实战教程(9)雨量计算与流量统计
ArcGIS水文分析实战教程(9)雨量计算与流量统计 本章导读:降水是水文循环中重要的一环,降水包括雨、雪、雾、露、雹等,本章介绍的是降雨的环节。通过雨量站与插值的方式,实现雨量的空间分布就算,…
【怎样写代码】函数式编程 -- Lambda表达式(四):Lambda表达式与Expression树
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

matlab svr 预测,SVR 多目标预测
程序代码:close all;clear;clc;format compact;load i_source.mat;% 提取数据[m,n] size(B);ts B(1:180,1);tsx B(1:180,2:n);figure;plot(ts,LineWidth,2);title(点信源波达方向随时间的变化规律,FontSize,12);xlabel(时间,FontSize,12);ylabel(波达方向,FontSi…
【建模必备】遗传算法的定义与生物学基础
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习。 If you like the content here, you can give me the greatest help is forwarding, tell your friends, encourage them to learn together.

转_前端开发技术概要
原文:http://www.2008sc.cn/blog/article.asp?id82 1、JavaScript 中的内存泄露模式http://www.ibm.com/developerworks/cn/web/wa-memleak/index.html----------------------2、javascript中的 闭包http://www.felixwoo.com/archives/247http://www.cn-cuckoo.com…

python中的类的成员变量以及property函数
1 python类的各种变量 1.1 全局变量 在类外定义的变量。 1.2 类变量 定义在类里面,所有的函数外面的变量。这个变量只有一份,是所有的对象共有的。在类外用“类.”来引用。 1.3 实例变量 用self.xxx在类的任何函数中定义的变量就是实例变量。在类内用“s…

php http面向对象编程实例,PHP面向对象编程——PHP对象引用实例代码
/*?* WEB开发笔记 www.chhua.com 每日练习 PHP面向对象编程——PHP对象引用实例代码?*//*代码演示?* */class HelloWorld {//被引用对象?public $world;?function __construct($world){??$this->world$world;?}??function getHtml(){??????? return “Hell…