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实现的Google IP 可用性检测脚本
Apr 23 Python
pygame游戏之旅 创建游戏窗口界面
Nov 20 Python
python中dict()的高级用法实现
Nov 13 Python
如何基于python操作json文件获取内容
Dec 24 Python
解决Pycharm中恢复被exclude的项目问题(pycharm source root)
Feb 14 Python
python调用HEG工具批量处理MODIS数据的方法及注意事项
Feb 18 Python
tensorflow常用函数API介绍
Apr 19 Python
在Ubuntu 20.04中安装Pycharm 2020.1的图文教程
Apr 30 Python
Python通过字典映射函数实现switch
Nov 06 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
Jan 21 Python
scrapy-splash简单使用详解
Feb 21 Python
Python面向对象编程之类的概念
Nov 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
PDO防注入原理分析以及注意事项
2015/02/25 PHP
Zend Framework教程之Zend_Config_Ini用法分析
2016/03/23 PHP
详解php中的implements 使用
2017/06/13 PHP
PHP代码重构方法漫谈
2018/04/17 PHP
PHP实现的AES双向加密解密功能示例【128位】
2018/09/03 PHP
在jQuery中 关于json空对象筛选替换
2013/04/15 Javascript
javascript 实现 秒杀,团购 倒计时展示的记录 分享
2013/07/12 Javascript
javascript对话框使用方法(警告框 javascript确认框 提示框)
2014/01/07 Javascript
原生js实现淘宝首页点击按钮缓慢回到顶部效果
2014/04/06 Javascript
浅谈JS中的bind方法与函数柯里化
2016/08/10 Javascript
微信小程序 video详解及简单实例
2017/01/16 Javascript
JS身份证信息验证正则表达式
2017/06/12 Javascript
JS中使用gulp实现压缩文件及浏览器热加载功能
2017/07/12 Javascript
JS实现按钮控制计时开始和停止功能
2017/07/27 Javascript
JS将网址url转化为JSON格式的方法
2018/07/02 Javascript
JS拖拽排序插件Sortable.js用法实例分析
2019/02/20 Javascript
JS/CSS实现字符串单词首字母大写功能
2019/09/03 Javascript
通过实例解析chrome如何在mac环境中安装vue-devtools插件
2020/07/10 Javascript
[33:15]2018DOTA2亚洲邀请赛3月30日 小组赛B组 VP VS Mineski
2018/03/31 DOTA
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python PyQt5实现的简易计算器功能示例
2017/08/23 Python
浅谈Python对内存的使用(深浅拷贝)
2018/01/17 Python
python数字图像处理之高级形态学处理
2018/04/27 Python
Python之time模块的时间戳,时间字符串格式化与转换方法(13位时间戳)
2019/08/12 Python
详解Python的爬虫框架 Scrapy
2020/08/03 Python
html5的canvas方法使用指南
2014/12/15 HTML / CSS
中国首家奢侈品O2O网购平台:第五大道奢侈品网
2017/12/14 全球购物
AssertionError 跟一下那个类是 “is – a”的关系
2012/02/21 面试题
分厂厂长岗位职责
2013/12/29 职场文书
表扬信格式
2014/01/12 职场文书
代理班主任的自我评价
2014/02/04 职场文书
工作表现自我评价
2014/02/08 职场文书
田径运动会通讯稿
2014/09/13 职场文书
检讨书范文300字
2015/01/28 职场文书
goland设置颜色和字体的操作
2021/05/05 Golang
详解Python常用的魔法方法
2021/06/03 Python