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实现猜数字游戏(无重复数字)示例分享
Mar 29 Python
Python入门教程之if语句的用法
May 14 Python
详解Python实现按任意键继续/退出的功能
Aug 19 Python
Python编程实现使用线性回归预测数据
Dec 07 Python
一个Python最简单的接口自动化框架
Jan 02 Python
python pandas修改列属性的方法详解
Jun 09 Python
使用python将大量数据导出到Excel中的小技巧分享
Jun 14 Python
Python中新式类与经典类的区别详析
Jul 10 Python
python 判断三个数字中的最大值实例代码
Jul 24 Python
200行python代码实现贪吃蛇游戏
Apr 24 Python
Django中使用Celery的方法步骤
Dec 07 Python
python 第三方库paramiko的常用方式
Feb 20 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
深入理解:XML与对象的序列化与反序列化
2013/06/08 PHP
php使用websocket示例详解
2014/03/12 PHP
php获取当月最后一天函数分享
2015/02/02 PHP
php将字符串随机分割成不同长度数组的方法
2015/06/01 PHP
PHP微信支付实例解析
2016/07/22 PHP
CI框架表单验证实例详解
2016/11/21 PHP
PHP实现的redis主从数据库状态检测功能示例
2017/07/20 PHP
Laravel获取当前请求的控制器和方法以及中间件的例子
2019/10/11 PHP
div+css布局的图片连续滚动js实现代码
2010/05/04 Javascript
微信开发 js实现tabs选项卡效果
2016/10/28 Javascript
JS中with的替代方法与String中的正则方法详解
2016/12/23 Javascript
jQuery上传多张图片带进度条样式(DEMO)
2017/03/02 Javascript
微信小程序中hidden不生效原因的解决办法
2017/04/26 Javascript
nodejs 搭建简易服务器的图文教程(推荐)
2017/07/18 NodeJs
基于DOM节点删除之empty和remove的区别(详解)
2017/09/11 Javascript
vue通过路由实现页面刷新的方法
2018/01/25 Javascript
JavaScript继承的特性与实践应用深入详解
2018/12/30 Javascript
AJAX在JQuery中的应用详解
2019/01/30 jQuery
vue下载excel的实现代码后台用post方法
2019/05/10 Javascript
vue项目中使用多选框的实例代码
2020/07/22 Javascript
js回到页面指定位置的三种方式
2020/12/17 Javascript
python实现系统状态监测和故障转移实例方法
2013/11/18 Python
Python批量修改文件后缀的方法
2014/01/26 Python
Python中字符编码简介、方法及使用建议
2015/01/08 Python
python中实现将多个print输出合成一个数组
2018/04/19 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
Django实现跨域请求过程详解
2019/07/25 Python
python创建与遍历List二维列表的方法
2019/08/16 Python
Python 词典(Dict) 加载与保存示例
2019/12/06 Python
python字典key不能是可以是啥类型
2020/08/04 Python
CSS去掉A标签(链接)虚线框的方法
2014/04/01 HTML / CSS
boostrap modal 闪现问题的解决方法
2020/09/01 HTML / CSS
英国领先的葡萄酒专家:Majestic Wine
2017/05/30 全球购物
十岁生日同学答谢词
2014/01/19 职场文书
应届生求职信
2014/05/31 职场文书
4s店销售经理岗位职责
2014/07/19 职场文书