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 的 with 语句详解
Jun 13 Python
安装dbus-python的简要教程
May 05 Python
Python使用文件锁实现进程间同步功能【基于fcntl模块】
Oct 16 Python
Python实现pdf文档转txt的方法示例
Jan 19 Python
如何使用 Pylint 来规范 Python 代码风格(来自IBM)
Apr 06 Python
python中的字符串内部换行方法
Jul 19 Python
Django model反向关联名称的方法
Dec 15 Python
Docker部署Python爬虫项目的方法步骤
Jan 19 Python
PyQt5.6+pycharm配置以及pyinstaller生成exe(小白教程)
Jun 02 Python
利用Python实现Excel的文件间的数据匹配功能
Jun 16 Python
一文轻松掌握python语言命名规范规则
Jun 18 Python
Python基础之常用库常用方法整理
Apr 30 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 xml 入门学习资料
2011/01/01 PHP
Window 7/XP 安装Apache 2.4与PHP 5.4 的过程详解
2013/06/02 PHP
屏蔽Flash右键信息的js代码
2010/01/17 Javascript
正则表达式搭配js轻松处理json文本方便而老古
2013/02/17 Javascript
JS调试必备的5个debug技巧
2014/03/07 Javascript
有关Promises异步问题详解
2015/11/13 Javascript
JS模拟的Map类实现方法
2016/06/17 Javascript
js正则表达式注册页面表单验证
2016/10/11 Javascript
用file标签实现多图文件上传预览
2017/02/14 Javascript
Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案
2017/03/13 Javascript
微信小程序组件传值图示过程详解
2019/07/31 Javascript
JS实现网页烟花动画效果
2020/03/10 Javascript
Vue3为什么这么快
2020/09/23 Javascript
Python sys.path详细介绍
2013/10/17 Python
Python卸载模块的方法汇总
2016/06/07 Python
numpy中矩阵合并的实例
2018/06/15 Python
python+selenium打印当前页面的titl和url方法
2018/06/22 Python
Python基于mysql实现学生管理系统
2019/02/21 Python
浅谈python新式类和旧式类区别
2019/04/26 Python
python读取目录下所有的jpg文件,并显示第一张图片的示例
2019/06/13 Python
python实现文件的备份流程详解
2019/06/18 Python
使用matlab 判断两个矩阵是否相等的实例
2020/05/11 Python
Python基于gevent实现文件字符串查找器
2020/08/11 Python
python绘图pyecharts+pandas的使用详解
2020/12/13 Python
纯CSS3实现运行时钟的示例代码
2021/01/25 HTML / CSS
美国婚礼礼品网站:MyWeddingFavors
2018/09/26 全球购物
聚网科技C++面试笔试题
2015/09/01 面试题
局域网标准
2016/09/10 面试题
JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
2013/07/02 面试题
素质拓展感言
2014/01/29 职场文书
领导失职检讨书
2014/02/24 职场文书
2014年纠风工作总结
2014/12/08 职场文书
运动会通讯稿100字
2015/07/20 职场文书
团支部组织委员竞选稿
2015/11/21 职场文书
运动会班级口号霸气押韵
2015/12/24 职场文书
Python实现信息轰炸工具(再也不怕说不过别人了)
2021/06/11 Python