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获取CPU和内存信息的思路与实现(linux系统)
Jan 03 Python
Python使用shelve模块实现简单数据存储的方法
May 20 Python
Python中的推导式使用详解
Jun 03 Python
Python中的日期时间处理详解
Nov 17 Python
基于Django与ajax之间的json传输方法
May 29 Python
Python循环中else,break和continue的用法实例详解
Jul 11 Python
python实现一个函数版的名片管理系统过程解析
Aug 27 Python
django配置app中的静态文件步骤
Mar 27 Python
浅谈JupyterNotebook导出pdf解决中文的问题
Apr 22 Python
Python matplotlib 绘制双Y轴曲线图的示例代码
Jun 12 Python
python获取系统内存占用信息的实例方法
Jul 17 Python
彻底解决pip下载pytorch慢的问题方法
Mar 01 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 APC配置文件2套和参数详解
2014/06/11 PHP
PHP类的声明与实例化及构造方法与析构方法详解
2016/01/26 PHP
Smarty模板变量调节器用法分析
2016/05/23 PHP
PHP递归实现汉诺塔问题的方法示例
2017/11/25 PHP
TP5(thinkPHP框架)实现后台清除缓存功能示例
2019/05/29 PHP
Javascript Function对象扩展之延时执行函数
2010/07/06 Javascript
javascript的内存管理详解
2013/08/07 Javascript
javascript判断office版本示例
2014/04/11 Javascript
浅谈javascript中call()、apply()、bind()的用法
2015/04/20 Javascript
使用Raygun来自动追踪AngularJS中的异常
2015/06/23 Javascript
jQuery模拟360浏览器切屏效果幻灯片(附demo源码下载)
2016/01/29 Javascript
jQuery中通过ajax调用webservice传递数组参数的问题实例详解
2016/05/20 Javascript
jQuery可见性过滤选择器用法示例
2016/09/09 Javascript
一步步教你利用Canvas对图片进行处理
2017/09/19 Javascript
vue中多路由表头吸顶实现的几种布局方式
2019/04/12 Javascript
vue封装可复用组件confirm,并绑定在vue原型上的示例
2019/10/31 Javascript
只有 20 行的 JavaScript 模板引擎实例详解
2020/05/11 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
2020/07/30 Javascript
[01:03:36]DOTA2-DPC中国联赛 正赛 VG vs Magma BO3 第二场 1月26日
2021/03/11 DOTA
精确查找PHP WEBSHELL木马的方法(1)
2011/04/12 Python
python数据结构之二叉树的遍历实例
2014/04/29 Python
Python配置mysql的教程(推荐)
2017/10/13 Python
Python程序运行原理图文解析
2018/02/10 Python
PYTHON基础-时间日期处理小结
2018/05/05 Python
Django 连接sql server数据库的方法
2018/06/30 Python
DES加密解密算法之python实现版(图文并茂)
2018/12/06 Python
详解Python3网络爬虫(二):利用urllib.urlopen向有道翻译发送数据获得翻译结果
2019/05/07 Python
Python matplotlib生成图片背景透明的示例代码
2019/08/30 Python
Koral官方网站:女性时尚运动服
2019/04/10 全球购物
医院护士的求职信范文
2013/12/26 职场文书
生产部统计员岗位职责
2014/01/05 职场文书
《陋室铭》教学反思
2014/02/26 职场文书
市场营销管理毕业生自荐信
2014/03/03 职场文书
个人房屋转让协议书范本
2014/10/26 职场文书
关于感谢信的范文
2015/01/23 职场文书
winserver2019安装软件一直卡在应用程序正在为首次使用做准备
2022/06/10 Servers