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的Flask框架中实现分页功能的教程
Apr 20 Python
python数组过滤实现方法
Jul 27 Python
详解Python函数作用域的LEGB顺序
May 14 Python
Python 中的with关键字使用详解
Sep 11 Python
Python 3中的yield from语法详解
Jan 18 Python
Queue 实现生产者消费者模型(实例讲解)
Nov 13 Python
python3 pandas 读取MySQL数据和插入的实例
Apr 20 Python
mac下给python3安装requests库和scrapy库的实例
Jun 13 Python
python提取包含关键字的整行数据方法
Dec 11 Python
Python + Requests + Unittest接口自动化测试实例分析
Dec 12 Python
Pytorch 搭建分类回归神经网络并用GPU进行加速的例子
Jan 09 Python
Python实现迪杰斯特拉算法并生成最短路径的示例代码
Dec 01 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中判断一个请求是ajax请求还是普通请求的方法
2011/06/28 PHP
PHP随机字符串生成代码(包括大小写字母)
2013/06/24 PHP
PHP实现批量生成App各种尺寸Logo
2015/03/19 PHP
php短信接口代码
2016/05/13 PHP
Yii框架where查询用法实例分析
2019/10/22 PHP
js Flash插入函数免激活代码
2009/03/31 Javascript
基于jquery的鼠标拖动效果代码
2012/05/30 Javascript
javascript窗口宽高,鼠标位置,滚动高度(详细解析)
2013/11/18 Javascript
Javascript四舍五入Math.round()与Math.pow()使用介绍
2013/12/27 Javascript
JS+CSS实现仿新浪微博搜索框的方法
2015/02/24 Javascript
JavaScript获得url查询参数的方法
2015/07/02 Javascript
jQuery进行组件开发完整实例
2015/12/15 Javascript
深入浅析JavaScript中的3DES
2016/08/24 Javascript
BootStrapValidator校验方式
2016/12/19 Javascript
微信小程序实现轮播图效果
2017/09/07 Javascript
vue 自定义组件 v-model双向绑定、 父子组件同步通信的多种写法
2017/11/27 Javascript
如何编写一个d.ts文件的步骤详解
2018/04/13 Javascript
详解ajax的data参数错误导致页面崩溃
2018/04/30 Javascript
vue 父组件给子组件传值子组件给父组件传值的实例代码
2019/04/15 Javascript
vue resource发送请求的几种方式
2019/09/30 Javascript
Python黑魔法Descriptor描述符的实例解析
2016/06/02 Python
Python中import机制详解
2017/11/14 Python
matplotlib设置legend图例代码示例
2017/12/19 Python
python文档字符串(函数使用说明)使用详解
2019/07/30 Python
Django中自定义admin Xadmin的实现代码
2019/08/09 Python
Python函数生成器原理及使用详解
2020/03/12 Python
世界第一冲浪品牌:O’Neill
2016/08/30 全球购物
优秀应届生推荐信
2013/11/09 职场文书
人事主管岗位职责
2014/01/30 职场文书
大课间体育活动方案
2014/03/12 职场文书
学校教师读书活动总结
2014/07/08 职场文书
公务员学习习总书记“三严三实”思想汇报
2014/09/19 职场文书
2014年销售工作总结范文
2014/12/01 职场文书
2015年乡镇卫生院工作总结
2015/04/22 职场文书
辩论赛新闻稿
2015/07/17 职场文书
postgreSQL数据库基础知识介绍
2022/04/12 PostgreSQL