博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python3-赋值与深浅拷贝(转载速查)
阅读量:6073 次
发布时间:2019-06-20

本文共 3429 字,大约阅读时间需要 11 分钟。

原链接:https://www.cnblogs.com/liushiyi/p/8195666.html

 

一、Python的变量及其存储

  在高级语言中,变量是对内存及其地址的抽象。对于python而言,python的一切变量都是对象,变量的存储,采用了引用语义的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量的本身。

  引用语义:在python中,变量保存的是对象(值)的引用,我们称为引用语义。采用这种语义,变量所需的存储空间大小一致,因为变量只是保存了一个引用。也被称为对象语义和指针语义。

  值语义:把变量的值直接保存在变量的存储区里,这种方式称为值语义。采用这种存储方式,每一个变量在内存中所占的空间就要根据变量实际的大小而定,无法固定下来。

  

二、各基本上数据结构的地址存储及改变情况

  在python中的数据类型包括:bool、int、long、float、str、set、list、tuple、dict等等。这些数据类型可以分为简单数据类型和复杂数据类型。

  简单数据类型和复杂数据类型的划分依据:如果一个数据类型,可以将其它的数据类型作为自己的元素,则可以认为这是一种数据结构。数据结构的分类有很多种,在Python中常用的只有集合、序列和映射三种结构。对应python中的set、list(tuple、str)、dict。常用的数据类型有int、long、float、bool、str等类型。

  

  由于python中的变量都是采用的引用语义,数据结构可以包含基础数据类型,导致了在python中的数据存储方式存在下图所示的这种情况,每个变量中都存储了这个变量的地址,而不是值本身;对于复杂的数据结构来说。里面的存储也只是每个元素的地址而已。

  1. 数据类型重新初始化对python语义引用的影响

  变量的每一次初始化,都开辟了一个新的空间,将新内容的地址赋值给变量。

>>> test = 'hello world'>>> id(test)4363600816>>> test = 'a new string' >>> id(test) 4363600880

  2. 数据结构内部元素变化对python语义的影响

  对于复杂的数据类型来说,改变其内部的值对于变量的影响:

>>> lst1 = [1,2,3,4,5]>>> id(lst1)4363600328>>> lst1.append('new item') >>> id(lst1) 4363600328 >>> lst1[0] = 'test item' >>> id(lst1) 4363600328 >>> lst1 = [1,2,3,4] >>> id(lst1) 4363600264

  当对列表中的元素进行一些增删改操作的时候,是不会影响到lst列表本身对于整个列表地址的,只会改变其内部元素的地址引用。可是当我们对于一个列表重新初始化(赋值)的时候,就给lst1这个变量重新赋予了一个地址,覆盖了原本列表的地址,这个时候,lst1列表的内存id就发生了改变。

三、变量的赋值

  1. 简单数据类型的赋值

>>> str1 = 'hello world'>>> str2 = str1>>> id(str1)4363601072>>> id(str2) 4363601072 >>> str1 = 'nihao' >>> id(str1) 4363608112 >>> id(str2) 4363601072

    

 

  看内存的变化,起始的赋值操作让str1和str2都存储了‘hello world’所在的地址,重新对str1初始化,是str1中存储的地址发生了改变,重新指向了新建的值,此时str2变量存储的内存地址并未改变,所以不受影响。

  2. 复杂数据结构中赋值

>>> lst1 = [1,2,3,4]>>> lst2 = lst1>>> id(lst1)4363600328>>> id(lst2)4363600328>>> lst1[0] = 'test' >>> lst1 ['test', 2, 3, 4] >>> lst2 ['test', 2, 3, 4]

  上述代码增加修改操作,但是并没有对lst2做出改变,结果lst1和lst2都发生了变化。

四、拷贝简述

  上述内容讲述了变量赋值的过程。对于复杂的数据结构来说,赋值就等于完全共享了资源,一个值的改变会完全被另一个值共享。

  然而有时候,我们偏偏需要将一份数据的原始内容保留一份,再去处理数据,这个时候使用赋值就不够明智了。python为这种需求提供了copy模块。提供了两种主要的copy方法,一种是普通的copy,另一种是deepcopy。我们称前者为浅拷贝,后者为深拷贝。

五、浅拷贝

  浅拷贝:不管多么复杂的数据结构、浅拷贝都只会copy一层。

  

import copylst = ['str1', 'str2', 'str3', 'str4', 'str5'] sourceLst = ['str1', 'str2', 'str3', 'str4', 'str5', lst] copyLst = copy.copy(sourceLst) print('1.->sourceLst:', sourceLst) print('1.->copyLst:', copyLst) sourceLst.append('sourcestr') copyLst.append('copystr') print('2.->sourceLst:', sourceLst) print('2.->copyLst:', copyLst) sourceLst[0] = 'changestr' print('3.->sourceLst:', sourceLst) print('3.->copyLst:', copyLst) lst.append('testAppend') print('4.->sourceLst:', sourceLst) print('4.->copyLst:', copyLst)

  上述代码执行会是下述结果:

1.->sourceLst: ['str1', 'str2', 'str3', 'str4', 'str5', ['str1', 'str2', 'str3', 'str4', 'str5']] 1.->copyLst: ['str1', 'str2', 'str3', 'str4', 'str5', ['str1', 'str2', 'str3', 'str4', 'str5']] 2.->sourceLst: ['str1', 'str2', 'str3', 'str4', 'str5', ['str1', 'str2', 'str3', 'str4', 'str5'], 'sourcestr'] 2.->copyLst: ['str1', 'str2', 'str3', 'str4', 'str5', ['str1', 'str2', 'str3', 'str4', 'str5'], 'copystr'] 3.->sourceLst: ['changestr', 'str2', 'str3', 'str4', 'str5', ['str1', 'str2', 'str3', 'str4', 'str5'], 'sourcestr'] 3.->copyLst: ['str1', 'str2', 'str3', 'str4', 'str5', ['str1', 'str2', 'str3', 'str4', 'str5'], 'copystr'] 4.->sourceLst: ['changestr', 'str2', 'str3', 'str4', 'str5', ['str1', 'str2', 'str3', 'str4', 'str5', 'testAppend'], 'sourcestr'] 4.->copyLst: ['str1', 'str2', 'str3

转载于:https://www.cnblogs.com/IMWU/p/10890697.html

你可能感兴趣的文章
Hibernate注解-实体类注解
查看>>
学习liunx决心书
查看>>
PHP 解析Maildir 邮件格式(eml文件)
查看>>
提升iOS审核通过率之“IPv6兼容测试”
查看>>
thinkphp配置文件数据库段配置
查看>>
专访孙睿 :能做自己,去做自己想做的,是件挺幸福的事儿
查看>>
开发者前期是如何学代码的(心得)
查看>>
Linux笔记(usermod命令,用户密码管理,mkpasswd)
查看>>
软件开发--深入浅出处理器
查看>>
文件查找命令
查看>>
文件权限管理
查看>>
链表节点的删除(无重复)
查看>>
eyoucms compare比较标签
查看>>
MPLS ×××概述
查看>>
jQuery+PHP+Mysql在线拍照和在线浏览照片
查看>>
nginx热部署升级
查看>>
使用JRockit 能否加速Myeclipse
查看>>
职场老司机才知道的Excel技巧,一般人不知道哦!
查看>>
Spring3与hibernate4注解式声明事务管理
查看>>
【linux下c语言服务器开发系列1】多进程处理多客户端的连接
查看>>