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之做一个小游戏
Sep 28 Python
Python Web框架Flask中使用新浪SAE云存储实例
Feb 08 Python
django开发教程之利用缓存文件进行页面缓存的方法
Nov 10 Python
python读取excel指定列数据并写入到新的excel方法
Jul 10 Python
Python基于滑动平均思想实现缺失数据填充的方法
Feb 21 Python
python实现扫描ip地址的小程序
Apr 16 Python
Selenium+Python 自动化操控登录界面实例(有简单验证码图片校验)
Jun 28 Python
Python表达式的优先级详解
Feb 18 Python
使用卷积神经网络(CNN)做人脸识别的示例代码
Mar 27 Python
Python 将 QQ 好友头像生成祝福语的实现代码
May 03 Python
python 用struct模块解决黏包问题
Nov 07 Python
Python 使用dict实现switch的操作
Apr 07 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
咖啡风味 世界咖啡主要分布分布 咖啡的生长要求
2021/03/06 新手入门
PHP 处理图片的类实现代码
2009/10/23 PHP
php获取ip的三个属性区别介绍(HTTP_X_FORWARDED_FOR,HTTP_VIA,REMOTE_ADDR)
2012/09/23 PHP
php中的路径问题与set_include_path使用介绍
2014/02/11 PHP
PHP+mysql实现从数据库获取下拉树功能示例
2017/01/06 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
IE和Firefox在JavaScript应用中的兼容性探讨
2008/04/01 Javascript
JavaScript入门教程(7) History历史对象
2009/01/31 Javascript
javascript将url中的参数加密解密代码
2014/11/17 Javascript
JS实现获取键盘按下的按键并显示在页面上的方法
2015/11/04 Javascript
javascript数组克隆简单实现方法
2015/12/16 Javascript
jquery.cookie实现的客户端购物车操作实例
2015/12/24 Javascript
AngularJS表达式讲解及示例代码
2016/08/16 Javascript
JS 实现随机验证码功能
2017/02/15 Javascript
使用Vue制作图片轮播组件思路详解
2018/03/21 Javascript
JavaScript中的E-mail 地址格式验证
2018/03/28 Javascript
VUE 3D轮播图封装实现方法
2018/07/03 Javascript
LayUI数据接口返回实体封装的例子
2019/09/12 Javascript
Vue 中 filter 与 computed 的区别与用法解析
2019/11/21 Javascript
vue实现数据控制视图的原理解析
2020/01/07 Javascript
Vue引入Stylus知识点总结
2020/01/16 Javascript
vue项目中使用particles实现粒子背景效果及遇到的坑(按钮没有点击响应)
2020/02/11 Javascript
解决Vue中使用keepAlive不缓存问题
2020/08/04 Javascript
详解Vue数据驱动原理
2020/11/17 Javascript
vue实现登录功能
2020/12/31 Vue.js
[36:16]完美世界DOTA2联赛PWL S3 access vs Rebirth 第一场 12.19
2020/12/24 DOTA
Python利用turtle库绘制彩虹代码示例
2017/12/20 Python
利用python为运维人员写一个监控脚本
2018/03/25 Python
基于python 二维数组及画图的实例详解
2018/04/03 Python
Python 3.8中实现functools.cached_property功能
2019/05/29 Python
python 批量修改 labelImg 生成的xml文件的方法
2019/09/09 Python
Django模板导入母版继承和自定义返回Html片段过程解析
2019/09/18 Python
css3针对移动端卡顿问题的解决(动画性能优化)
2020/02/14 HTML / CSS
商业门面租房协议书
2014/11/25 职场文书
2014年银行年终工作总结
2014/12/19 职场文书
美德少年主要事迹材料
2015/11/04 职场文书