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装饰器使用方法实例
Nov 21 Python
Python高级应用实例对比:高效计算大文件中的最长行的长度
Jun 08 Python
Python实现的HTTP并发测试完整示例
Apr 23 Python
Django中传递参数到URLconf的视图函数中的方法
Jul 18 Python
深入解析Python中函数的参数与作用域
Mar 20 Python
python文件的md5加密方法
Apr 06 Python
Windows下安装python2和python3多版本教程
Mar 30 Python
python编写暴力破解zip文档程序的实例讲解
Apr 24 Python
浅析Python四种数据类型
Sep 26 Python
Python命名空间的本质和加载顺序
Dec 17 Python
python 变量初始化空列表的例子
Nov 28 Python
利用Tensorflow构建和训练自己的CNN来做简单的验证码识别方式
Jan 20 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 filter_var() 函数 Filter 函数
2012/04/25 PHP
php格式化日期和时间格式化示例分享
2014/02/24 PHP
PHP商品秒杀问题解决方案实例详解【mysql与redis】
2019/07/22 PHP
jquery 插件 人性化的消息显示
2008/01/21 Javascript
关于Aptana Studio生成自动备份文件的解决办法
2009/12/23 Javascript
jQuery中使用Ajax获取JSON格式数据示例代码
2013/11/26 Javascript
extJS中常用的4种Ajax异步提交方式
2014/03/07 Javascript
Windows8下搭建Node.js开发环境教程
2014/09/03 Javascript
jqTransform美化表单
2015/10/10 Javascript
JavaScript Math 对象常用方法总结
2016/04/28 Javascript
浅析js绑定事件的常用方法
2016/05/15 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(二)
2017/05/11 Javascript
在vue中解决提示警告 for循环报错的方法
2018/09/28 Javascript
关于angular 8.1使用过程中的一些记录
2020/11/25 Javascript
[11:57]《一刀刀一天》第十七期:TI中国军团加油!
2014/05/26 DOTA
[55:47]DOTA2上海特级锦标赛C组小组赛#2 LGD VS Newbee第三局
2016/02/27 DOTA
python更新列表的方法
2015/07/28 Python
Python使用min、max函数查找二维数据矩阵中最小、最大值的方法
2018/05/15 Python
Python动态生成多维数组的方法示例
2018/08/09 Python
Ubuntu下Python2与Python3的共存问题
2018/10/31 Python
在Python 中实现图片加框和加字的方法
2019/01/26 Python
python openpyxl使用方法详解
2019/07/18 Python
pycharm软件实现设置自动保存操作
2020/06/08 Python
PyCharm2020.1.2社区版安装,配置及使用教程详解(Windows)
2020/08/07 Python
python制作微博图片爬取工具
2021/01/16 Python
css3中background新增的4个新的相关属性用法介绍
2013/09/26 HTML / CSS
详解Html5 Canvas画线有毛边解决方法
2018/03/01 HTML / CSS
Champion澳大利亚官网:美国冠军运动服装
2018/05/07 全球购物
有个性的自我评价范文
2013/11/15 职场文书
医学生职业生涯规划书范文
2014/03/13 职场文书
人力资源管理专业毕业生自荐书
2014/05/25 职场文书
五四青年节优秀演讲稿范文
2014/05/28 职场文书
2014年大学班级工作总结
2014/11/14 职场文书
解决Goland 同一个package中函数互相调用的问题
2021/05/06 Golang
react国际化react-intl的使用
2021/05/06 Javascript
Win11右下角图标点了没反应怎么办?Win11点击右下角图标无反应解决方法汇总
2022/07/07 数码科技