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判断给定的字符串是否是有效日期的方法
May 13 Python
Python中int()函数的用法浅析
Oct 17 Python
Python实现图片滑动式验证识别方法
Nov 09 Python
Python+tkinter使用80行代码实现一个计算器实例
Jan 16 Python
Python 实现一行输入多个值的方法
Apr 21 Python
对python requests的content和text方法的区别详解
Oct 11 Python
Python实现根据日期获取当天凌晨时间戳的方法示例
Apr 09 Python
Python集合基本概念与相关操作实例分析
Oct 30 Python
对python中 math模块下 atan 和 atan2的区别详解
Jan 17 Python
基于python检查SSL证书到期情况代码实例
Apr 04 Python
OpenCV-Python实现轮廓的特征值
Jun 09 Python
Python使用psutil库对系统数据进行采集监控的方法
Aug 23 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
深入apache host的配置详解
2013/06/09 PHP
php判断用户是否手机访问代码
2015/06/08 PHP
PHP和C#可共用的可逆加密算法详解
2015/10/26 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
详解PHP序列化和反序列化原理
2018/01/15 PHP
Javascript & DHTML 实例编程(教程)(三)初级实例篇1—上传文件控件实例
2007/06/02 Javascript
javascript 添加和移除函数的通用方法
2009/10/20 Javascript
jquery动画3.创建一个带遮罩效果的图片走廊
2012/08/24 Javascript
JQuery中使用Ajax赋值给全局变量异常的解决方法
2014/01/10 Javascript
为指定的元素添加遮罩层的示例代码
2014/01/15 Javascript
JavaScript使用addEventListener添加事件监听用法实例
2015/06/01 Javascript
Bootstrap基本样式学习笔记之按钮(4)
2016/12/07 Javascript
JS对象是否拥有某属性如何判断
2017/02/03 Javascript
在vue中添加Echarts图表的基本使用教程
2017/11/22 Javascript
webstorm中vue语法的支持详解
2018/05/09 Javascript
Bootstrap简单实用的表单验证插件BootstrapValidator用法实例详解
2020/03/29 Javascript
js实现全选和全不选
2020/07/28 Javascript
详解Vue的组件中data选项为什么必须是函数
2020/08/17 Javascript
Openlayers实现测量功能
2020/09/25 Javascript
[01:10:03]OG vs EG 2018国际邀请赛淘汰赛BO3 第三场 8.23
2018/08/24 DOTA
Python 实现数据库更新脚本的生成方法
2017/07/09 Python
python中文分词教程之前向最大正向匹配算法详解
2017/11/02 Python
Python+Pandas 获取数据库并加入DataFrame的实例
2018/07/25 Python
详解Python中的type和object
2018/08/15 Python
PyCharm上安装Package的实现(以pandas为例)
2020/09/18 Python
美国乡村商店:Plow & Hearth
2016/09/12 全球购物
Charlotte Tilbury英国官网:英国彩妆品牌
2017/05/26 全球购物
皇家阿尔伯特英国官方商店:Royal Albert骨瓷
2019/03/25 全球购物
DBA数据库管理员JAVA程序员架构师必看
2016/02/07 面试题
追悼会上的答谢词
2014/01/10 职场文书
幼儿园教师工作制度
2014/01/22 职场文书
高中生的自我评价
2014/03/04 职场文书
警示教育活动总结
2014/05/05 职场文书
诚信承诺书
2015/01/19 职场文书
深入理解mysql事务隔离级别和存储引擎
2022/04/12 MySQL
css之clearfix的用法深入理解(必看篇)
2023/05/21 HTML / CSS