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 18 Python
Python中使用装饰器时需要注意的一些问题
May 11 Python
python实现简单登陆系统
Oct 18 Python
python批量修改文件夹及其子文件夹下的文件内容
Mar 15 Python
Python3.5 Pandas模块之Series用法实例分析
Apr 23 Python
详解pandas数据合并与重塑(pd.concat篇)
Jul 09 Python
pandas中遍历dataframe的每一个元素的实现
Oct 23 Python
python Qt5实现窗体跟踪鼠标移动
Dec 13 Python
在django项目中导出数据到excel文件并实现下载的功能
Mar 13 Python
Pycharm激活方法及详细教程(详细且实用)
May 12 Python
你需要学会的8个Python列表技巧
Jun 24 Python
如何更换python默认编辑器的背景色
Aug 10 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
《Re:从零开始的异世界生活 冰结之绊》
2020/04/09 日漫
PHP 错误之引号中使用变量
2009/05/04 PHP
PHP投票系统防刷票判断流程分析
2012/02/04 PHP
必须收藏的23个php实用代码片段
2016/02/02 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
thinkphp分页集成实例
2017/07/24 PHP
php设计模式之装饰模式应用案例详解
2019/06/17 PHP
jQuery MD5加密实现代码
2010/03/15 Javascript
nodejs 后缀名判断限制代码
2011/03/31 NodeJs
js实现在文本框光标处添加字符的方法介绍
2012/11/24 Javascript
js操作IE浏览器弹出浏览文件夹可以返回目录路径
2014/07/14 Javascript
使用mouse事件实现简单的鼠标经过特效
2015/01/30 Javascript
JavaScript面对国际化编程时的一些建议
2015/06/24 Javascript
Node.js中JavaScript操作MySQL的常用方法整理
2016/03/01 Javascript
VUEJS实战之修复错误并且美化时间(2)
2016/06/13 Javascript
JS实现多张图片预览同步上传功能
2017/06/23 Javascript
解决Vue.js 2.0 有时双向绑定img src属性失败的问题
2018/03/14 Javascript
详解如何创建并发布一个 vue 组件
2018/11/08 Javascript
jQuery使用$.extend(true,object1, object2);实现深拷贝对象的方法分析
2019/03/06 jQuery
js实现轮播图特效
2020/05/28 Javascript
[06:07]DOTA2-DPC中国联赛3月5日Recap集锦
2021/03/11 DOTA
详解Python命令行解析工具Argparse
2016/04/20 Python
Python即时网络爬虫项目启动说明详解
2018/02/23 Python
在pandas中一次性删除dataframe的多个列方法
2018/04/10 Python
Python字典遍历操作实例小结
2019/03/05 Python
python使用装饰器作日志处理的方法
2019/07/11 Python
Python测试模块doctest使用解析
2019/08/10 Python
python生成任意频率正弦波方式
2020/02/25 Python
python3中的logging记录日志实现过程及封装成类的操作
2020/05/12 Python
自我评价是什么
2014/01/04 职场文书
工作自我评价怎么写
2014/01/29 职场文书
公司周年庆典策划方案
2014/05/17 职场文书
2015-2016年小学教导工作总结
2015/07/21 职场文书
《兰兰过桥》教学反思
2016/02/20 职场文书
详细聊聊MySQL中慢SQL优化的方向
2021/08/30 MySQL
Python安装使用Scrapy框架
2022/04/12 Python