Python中实现变量赋值传递时的引用和拷贝方法


Posted in Python onApril 29, 2018

iamlaosong文

曾经看到这样一个问题,一个字典中的元素是列表,将这个列表元素赋值给一个变量,然后修改这个列表中元素的值,结果发现,字典中那个列表也同样修改了。

那个问题如下:

dict = {'a':[1,2,3,4,5],'b':2} 
x = dict['a'] 
for i in range(5): 
  x[i] = 0 
print(dict['a'])

程序运行结果如下:

[0, 0, 0, 0, 0]

这儿涉及到Python赋值到底是引用还是拷贝一份的问题,即赋值时是传值还是传址。上面问题是将“a”的值赋给了x出现了上述情况,如果是将“b”的值赋给了x,当我们修改x的值时,字典dict的值并不受影响。

>>> dict = {'a':[1,2,3,4,5],'b':2} 
>>> x = dict['b'] 
>>> x 
2 
>>> x=x+3 
>>> x 
5 
>>> dict 
{'a': [1, 2, 3, 4, 5], 'b': 2} 
>>>

那么问题来了,变量赋值传递时什么情况下是传值(拷贝),什么情况下是传址(引用)呢?

1、直接拷贝

当我们不知道是引用还是拷贝的情况下,可以显式的拷贝。比如字典对象本身都具有拷贝的方法:

x=dict.copy()

没有拷贝方法的对象,也是可以拷贝的。这儿我们引入一个深拷贝的概念,深拷贝——即python的copy模块提供的一个deepcopy方法。深拷贝会完全复制原变量相关的所有数据,在内存中生成一套完全一样的内容,在这个过程中我们对这两个变量中的一个进行任意修改都不会影响其他变量。还是上面的代码,如果改成如下:

import copy 
dict = {'a':[1,2,3,4,5],'b':2} 
x = copy.deepcopy(dict['a']) 
for i in range(5): 
  x[i] = 0 
print(dict['a'])

运行结果dict值不受影响。

除了深拷贝,copy模块还提供一个copy方法,称其为浅拷贝,对于简单的对象,深浅拷贝都是一样的,上面的词典对象的copy方法就是浅拷贝。

>>> dict
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd=copy.copy(dict)
>>> dd
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd['a'][0]=7
>>> dd
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee=dict.copy()
>>> ee
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee['a'][0]=9
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> ee['b']=5
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 5}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>>

浅拷贝时改变第一层次相互不受影响(上例中词典b值的修改),第二层次(上例中词典a的列表值修改)就相互影响了,改一个,其他跟着变。看看id吧:

>>> id(dict) 
20109472 
>>> id(dd) 
20244496 
>>> id(ee) 
20495072 
>>> id(dd['a']) 
20272112 
>>> id(ee['a']) 
20272112 
>>> id(dict['a']) 
20272112 
>>>

可见词典各个拷贝的id是不同的,但词典a值的id是相同的。如果我们需要真正意义的拷贝,就用深拷贝吧。

2、传递规则

Python赋值过程中不明确区分拷贝和引用,一般对静态变量的传递为拷贝,对动态变量的传递为引用。(注,对静态变量首次传递时也是引用,当需要修改静态变量时,因为静态变量不能改变,所以需要生成一个新的空间存储数据)。

字符串,数值,元组均为静态变量

列表,字典为动态变量。

变量有时比较复杂,存在组合现象,比如字典中包含列表,列表中包含字典,但赋值时,总是属于某个类型。如果实在不清楚状况,可以试验一下,用id()这个函数看看,如果是引用,两个变量指向的地址是相同的。例如:

>>> a=6 
>>> id(a) 
10413476 
>>> b=a 
>>> id(b) 
10413476 
>>> b=8 
>>> id(b) 
10413452 
>>>

修改变量b之前,a和b指向的地址是相同的,修改b后,地址就变了。

以上这篇Python中实现变量赋值传递时的引用和拷贝方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中使用urllib2伪造HTTP报头的2个方法
Jul 07 Python
python使用arp欺骗伪造网关的方法
Apr 24 Python
Anaconda入门使用总结
Apr 05 Python
让Django支持Sql Server作后端数据库的方法
May 29 Python
python爬取个性签名的方法
Jun 17 Python
解决python读取几千万行的大表内存问题
Jun 26 Python
python队列Queue的详解
May 10 Python
wxPython色环电阻计算器
Nov 18 Python
使用python远程操作linux过程解析
Dec 04 Python
利用setuptools打包python程序的方法步骤
Jan 18 Python
Python爬虫库requests获取响应内容、响应状态码、响应头
Jan 25 Python
Python闭包的定义和使用方法
Apr 11 Python
分享一下Python数据分析常用的8款工具
Apr 29 #Python
Python随机函数random()使用方法小结
Apr 29 #Python
Python中py文件引用另一个py文件变量的方法
Apr 29 #Python
python实现类之间的方法互相调用
Apr 29 #Python
Python装饰器原理与简单用法实例分析
Apr 29 #Python
Python2.7 实现引入自己写的类方法
Apr 29 #Python
Python 实现引用其他.py文件中的类和类的方法
Apr 29 #Python
You might like
php 小乘法表实现代码
2009/07/16 PHP
PHP入门教程之上传文件实例详解
2016/09/11 PHP
PHP实现删除多重数组对象属性并重新赋值的方法
2017/06/07 PHP
jquery uaMatch源代码
2011/02/14 Javascript
JavaScript中的16进制字符(改进)
2011/11/21 Javascript
php+js实现倒计时功能
2014/06/02 Javascript
深入理解JavaScript系列(35):设计模式之迭代器模式详解
2015/03/03 Javascript
JavaScript控制listbox列表框的项目上下移动的方法
2015/03/18 Javascript
Javascript实现的简单右键菜单类
2015/09/23 Javascript
初步使用bootstrap快速创建页面
2016/03/03 Javascript
JS中BOM相关知识点总结(必看篇)
2016/11/22 Javascript
基于javascript实现最简单选项卡切换
2017/02/01 Javascript
jQuery手风琴的简单制作
2017/05/12 jQuery
vue基于两个计算属性实现选中和全选功能示例
2019/02/08 Javascript
JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】
2019/02/18 Javascript
jQuery Migrate 插件用法实例详解
2019/05/22 jQuery
JS数组Object.keys()方法的使用示例
2019/06/05 Javascript
[01:25:09]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第二场
2014/05/24 DOTA
Python利用Beautiful Soup模块搜索内容详解
2017/03/29 Python
Python 关于反射和类的特殊成员方法
2017/09/14 Python
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
windows安装TensorFlow和Keras遇到的问题及其解决方法
2019/07/10 Python
pycharm配置当鼠标悬停时快速提示方法参数
2019/07/31 Python
Django 项目重命名的实现步骤解析
2019/08/14 Python
Python 读取 YUV(NV12) 视频文件实例
2019/12/09 Python
opencv之为图像添加边界的方法示例
2019/12/26 Python
美国生鲜及杂货电商:FreshDirect
2018/01/29 全球购物
Servlet如何得到服务器的信息
2015/12/22 面试题
医学专业本科毕业生自我鉴定
2013/12/28 职场文书
航空学院求职信
2014/06/11 职场文书
另类冲刺标语
2014/06/24 职场文书
苦儿流浪记读书笔记
2015/07/01 职场文书
2016年“9.22”世界无车日活动小结
2016/04/05 职场文书
2019辞职报告范本3篇!
2019/07/23 职场文书
自动在Windows中运行Python脚本并定时触发功能实现
2021/09/04 Python
进行数据处理的6个 Python 代码块分享
2022/04/06 Python