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实现一次创建多级目录的方法
May 15 Python
在Django的视图中使用数据库查询的方法
Jul 16 Python
快速解决安装python没有scripts文件夹的问题
Apr 03 Python
将python代码和注释分离的方法
Apr 21 Python
Python实现计算圆周率π的值到任意位的方法示例
May 08 Python
python pandas中对Series数据进行轴向连接的实例
Jun 08 Python
对numpy中的数组条件筛选功能详解
Jul 02 Python
解决win64 Python下安装PIL出错问题(图解)
Sep 03 Python
使用Django搭建web服务器的例子(最最正确的方式)
Aug 29 Python
python 采用paramiko 远程执行命令及报错解决
Oct 21 Python
python selenium 获取接口数据的实现
Dec 07 Python
ubuntu安装jupyter并设置远程访问的实现
Mar 31 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中ltrim()、rtrim()与trim()删除字符空格实例
2014/11/25 PHP
Json_encode防止汉字转义成unicode的方法
2016/02/25 PHP
PHP5.2中PDO的简单使用方法
2016/03/25 PHP
PHP未登录自动跳转到登录页面
2016/12/21 PHP
PHP的mysqli_ssl_set()函数讲解
2019/01/23 PHP
js控制框架刷新
2008/08/01 Javascript
jQuery 使用手册(三)
2009/09/23 Javascript
javascript getElementsByTagName
2011/01/31 Javascript
Javascript之this关键字深入解析
2013/11/12 Javascript
给事件响应函数传参数的四种方式小结
2013/12/05 Javascript
js实现键盘控制DIV移动的方法
2015/01/10 Javascript
Grunt入门教程(自动任务运行器)
2015/08/06 Javascript
javascript实现状态栏中文字动态显示的方法
2015/10/20 Javascript
JS插件overlib用法实例详解
2015/12/26 Javascript
基于jQuery实现仿百度首页选项卡切换效果
2016/05/29 Javascript
jquery对象和DOM对象的相互转换详解
2016/10/18 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单
2016/11/25 Javascript
通过BootStrap-select插件 js jQuery控制select属性变化
2017/01/03 Javascript
vue.js实现条件渲染的实例代码
2017/06/22 Javascript
深入理解Vue 单向数据流的原理
2017/11/09 Javascript
vue input输入框模糊查询的示例代码
2018/05/22 Javascript
JS中如何轻松遍历对象属性的方式总结
2019/08/06 Javascript
Python遍历指定文件及文件夹的方法
2015/05/09 Python
python读取TXT到数组及列表去重后按原来顺序排序的方法
2015/06/26 Python
利用pyuic5将ui文件转换为py文件的方法
2019/06/19 Python
关于tf.nn.dynamic_rnn返回值详解
2020/01/20 Python
TensorFlow dataset.shuffle、batch、repeat的使用详解
2020/01/21 Python
Python基于pyecharts实现关联图绘制
2020/03/27 Python
CSS3+JavaScript实现炫酷呼吸效果的示例代码
2020/06/15 HTML / CSS
用html5的canvas和JavaScript创建一个绘图程序的简单实例
2016/07/06 HTML / CSS
网络工程专业自荐信范文
2014/03/16 职场文书
投标人法定代表人授权委托书格式
2014/09/28 职场文书
党员三严三实心得体会
2014/10/13 职场文书
门面租赁合同范文
2019/08/06 职场文书
常用的Python代码调试工具总结
2021/06/23 Python
eval(cmd)与eval($cmd)的区别与联系
2021/07/07 PHP