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 11 Python
教大家玩转Python字符串处理的七种技巧
Mar 31 Python
Python实现的排列组合计算操作示例
Oct 13 Python
Python numpy 常用函数总结
Dec 07 Python
Django 根据数据模型models创建数据表的实例
May 27 Python
python 字符串和整数的转换方法
Jun 25 Python
Python中安装easy_install的方法
Nov 18 Python
opencv调整图像亮度对比度的示例代码
Sep 27 Python
Django 博客实现简单的全文搜索的示例代码
Feb 17 Python
如何把外网python虚拟环境迁移到内网
May 18 Python
pyMySQL SQL语句传参问题,单个参数或多个参数说明
Jun 06 Python
python打开音乐文件的实例方法
Jul 21 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中is_file()函数使用指南
2015/05/08 PHP
php根据用户语言跳转相应网页
2015/11/04 PHP
php编程每天必学之验证码
2016/03/03 PHP
PHP使用PDO操作sqlite数据库应用案例
2019/03/07 PHP
PHP从零开始打造自己的MVC框架之入口文件实现方法详解
2019/06/03 PHP
top.location.href 没有权限 解决方法
2008/08/05 Javascript
jquery插件之easing使用
2010/08/19 Javascript
基本jquery的控制tabs打开的数量的代码
2010/10/17 Javascript
jquery判断小数点两位和自动删除小数两位后的数字
2014/03/19 Javascript
解决jquery实现的radio重新选中的问题
2015/07/03 Javascript
JavaScript动态添加css样式和script标签
2016/07/19 Javascript
原生js实现打字动画游戏
2017/02/04 Javascript
JS实现直接运行html代码的方法
2017/03/13 Javascript
Angular4学习教程之HTML属性绑定的方法
2018/01/04 Javascript
JavaScript实现淘宝京东6位数字支付密码效果
2018/08/18 Javascript
Element-ui tree组件自定义节点使用方法代码详解
2018/09/17 Javascript
Angular设置别名alias的方法
2018/11/08 Javascript
详解ES6系列之私有变量的实现
2018/11/21 Javascript
react组件从搭建脚手架到在npm发布的步骤实现
2019/01/09 Javascript
微信小程序文章详情页跳转案例详解
2019/07/09 Javascript
解决webpack多页面内存溢出的方法示例
2019/10/08 Javascript
浅谈vuex的基本用法和mapaction传值问题
2019/11/08 Javascript
微信小程序自定义纯净模态框(弹出框)的实例代码
2020/03/09 Javascript
vue用elementui写form表单时,在label里添加空格操作
2020/08/13 Javascript
Vue+element-ui添加自定义右键菜单的方法示例
2020/12/08 Vue.js
Python深入学习之特殊方法与多范式
2014/08/31 Python
Python使用minidom读写xml的方法
2015/06/03 Python
Python在图片中添加文字的两种方法
2017/04/29 Python
python matplotlib中文显示参数设置解析
2017/12/15 Python
Python 实现敏感目录扫描的示例代码
2020/05/21 Python
k-means 聚类算法与Python实现代码
2020/06/01 Python
使用Keras建立模型并训练等一系列操作方式
2020/07/02 Python
基于python图书馆管理系统设计实例详解
2020/08/05 Python
浅谈Python 钉钉报警必备知识系统讲解
2020/08/17 Python
澳大利亚厨房和家用电器购物网站:Bing Lee
2021/01/11 全球购物
社区十八大感言
2014/01/19 职场文书