Python中的引用和拷贝浅析


Posted in Python onNovember 22, 2014

If an object's value can be modified, the object is said to be mutable. If the value cannot be modified,the object is said to be immutable.

mutable 可变类型,例如 list,set,自定义类型(等价于C#中的引用类型);

immutable 不可变类型,例如string,numbers等(等价于C#中的值类型);

一、引用和拷贝(references and copies)

当程序中使用=赋值操作符时,例如a=b,

对于不可变的对象,a作为b的一个拷贝被创建,a和b将指向不同的内存地址,a和b相互独立。

def TestCopy():

    a = 10

    b = a

    a =20

    print (b) #b still is 10

但是对于可变的对象,a作为b的一个引用被创建,a和b的元素公用相同的内存地址,a和b的元素共享。
def TestRef():

    a=[1,2,3,4]

    b=a   #b is a reference to a

    print (b is a) # True

    b[2] = -100 #change an element in b

    print (a) # a also changed to [1,2,-100,4]

二、深拷贝和浅拷贝(shallow copy and deep copy)

为了避免可变对象指向同一个对象,必须创建一个新的拷贝,而不是引用。
在python中可以对容器对象(例如lists和dictionaries)使用两种拷贝:浅拷贝和深拷贝。
 
浅拷贝创建一个新的对象,但是使用原来对象的元素的引用(如果是不变类型,相当于是拷贝)来填充新对象。可以使用copy.copy()来实现浅拷贝。

def TestShallowCopy():

    a = [ 1, 2, [3,4] ]

    b = list(a) # create a shallow copy of a

    print (b is a) #False

    b.append(100) #append element to b

    print (b)

    print (a) # a is unchanged

    b[2][0] = -100 # modify an element inside b

    print (b)

    print (a)  # a is changed

在这个例子中,a和b共享相同的可变元素。所以修改其中一个list对象中的元素,另一个list对象也会被修改。

深拷贝创建一个新的对象,同时递归地拷贝对象所包含的所有的元素。可以使用copy.deepcopy()来实现深拷贝。

def TestDeepCopy():

  import copy

  a = [1, 2, [3, 4]]

  b = copy.deepcopy(a)

  b[2][0] = -100

  print (b)  # b is changed

  print (a)  # a is unchanged

在这个例子中,a和b是对立的list对象,且他们的元素也相互独立。

三、引用计数和垃圾回收

python中的所有的对象都是引用计数的,一个对象赋值或加入容器时,它的引用计数就会自增,当使用del时或变量赋值为其他值时,引用计数就会自减,当引用计数为0时,python的垃圾回收器就会回收该变量。

def TestGarbageCollection():

  import sys

  print(sys.getrefcount(37))

  a = 37 # Creates an object with value 37

  print(sys.getrefcount(37))

  b = a # Increases reference count on 37

  print(sys.getrefcount(37))

  c = []

  c.append(b) # Increases reference count on 37

  print(sys.getrefcount(37))

  del a # Decrease reference count of 37

  print(sys.getrefcount(37))

  b = 42 # Decrease reference count of 37

  print(sys.getrefcount(37))

  c[0] = 2.0 # Decrease reference count of 37

  print(sys.getrefcount(37)) 

  

TestGarbageCollection()

运行结果为:

11

12

13

14

13

12

11

为啥一上来就有11个引用了呢?谁知道?
Python 相关文章推荐
下载糗事百科的内容_python版
Dec 07 Python
详细介绍Python语言中的按位运算符
Nov 26 Python
python处理文本文件实现生成指定格式文件的方法
Jul 31 Python
python遍历目录的方法小结
Apr 28 Python
Python+matplotlib实现计算两个信号的交叉谱密度实例
Jan 08 Python
python3+PyQt5使用数据库窗口视图
Apr 24 Python
朴素贝叶斯Python实例及解析
Nov 19 Python
python全栈知识点总结
Jul 01 Python
使用python 将图片复制到系统剪贴中
Dec 13 Python
PyTorch实现AlexNet示例
Jan 14 Python
python编程进阶之异常处理用法实例分析
Feb 21 Python
Python中的With语句的使用及原理
Jul 29 Python
python实现的文件夹清理程序分享
Nov 22 #Python
Python判断操作系统类型代码分享
Nov 22 #Python
python logging类库使用例子
Nov 22 #Python
Python中模拟enum枚举类型的5种方法分享
Nov 22 #Python
Python读写Excel文件方法介绍
Nov 22 #Python
Python中的包和模块实例
Nov 22 #Python
Python动态加载模块的3种方法
Nov 22 #Python
You might like
php防注入及开发安全详细解析
2013/08/09 PHP
php中使用Ajax时出现Error(c00ce56e)的详细解决方案
2014/11/03 PHP
PHP获取页面执行时间的方法(推荐)
2016/12/10 PHP
可输入的下拉框
2006/06/19 Javascript
js 替换
2008/02/19 Javascript
Javascript数组操作函数总结
2015/02/05 Javascript
jQuery蓝色风格滑动导航栏代码分享
2015/08/19 Javascript
js实现网页收藏功能
2015/12/17 Javascript
基于javascript实现右下角浮动广告效果
2016/01/08 Javascript
jQuery元素属性操作实例(设置、获取及删除元素属性)
2016/09/08 Javascript
jQuery中table数据的值拷贝和拆分
2017/03/19 Javascript
JavaScript 值类型和引用类型的初次研究(推荐)
2017/07/19 Javascript
Vue脚手架的简单使用实例
2018/07/10 Javascript
Angular5.0 子组件通过service传递值给父组件的方法
2018/07/13 Javascript
node.js调用C++函数的方法示例
2018/09/21 Javascript
vue-router传递参数的几种方式实例详解
2018/11/13 Javascript
vue使用codemirror的两种用法
2019/08/27 Javascript
js节流防抖应用场景,以及在vue中节流防抖的具体实现操作
2020/09/21 Javascript
[06:16]DOTA2守卫传承者——职业选手谈心路历程
2015/02/26 DOTA
python贪婪匹配以及多行匹配的实例讲解
2018/04/19 Python
python twilio模块实现发送手机短信功能
2019/08/02 Python
通过实例解析python描述符原理作用
2020/01/22 Python
python实现飞船游戏的纵向移动
2020/04/24 Python
python IDLE添加行号显示教程
2020/04/25 Python
django中嵌套的try-except实例
2020/05/21 Python
Django Model层F,Q对象和聚合函数原理解析
2020/11/12 Python
python爬虫看看虎牙女主播中谁最“顶”步骤详解
2020/12/01 Python
Dr. Martens马汀博士澳大利亚官网:马丁靴鼻祖
2019/07/02 全球购物
Europcar比利时:租车
2019/08/26 全球购物
演讲比赛获奖感言
2014/02/02 职场文书
《听鱼说话》教学反思
2014/02/15 职场文书
2014年班主任自我评价范文
2014/04/23 职场文书
宣传口号大全
2014/06/16 职场文书
自主招生学校推荐信
2014/09/26 职场文书
关于对大人不礼貌的检讨书
2014/09/29 职场文书
建房合同协议书
2016/03/21 职场文书