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实现斐波那契(Fibonacci)函数
Mar 25 Python
Centos Python2 升级到Python3的简单实现
Jun 21 Python
windows下Python实现将pdf文件转化为png格式图片的方法
Jul 21 Python
Python 文件操作的详解及实例
Sep 18 Python
对python 各种删除文件失败的处理方式分享
Apr 24 Python
Python实现的爬取网易动态评论操作示例
Jun 06 Python
Python3.4解释器用法简单示例
Mar 22 Python
Python实现直方图均衡基本原理解析
Aug 08 Python
python 实现在无序数组中找到中位数方法
Mar 03 Python
Keras:Unet网络实现多类语义分割方式
Jun 11 Python
PyTorch实现重写/改写Dataset并载入Dataloader
Jul 14 Python
Python限制内存和CPU使用量的方法(Unix系统适用)
Aug 04 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动态生成VRML网页
2006/10/09 PHP
APMServ使用说明
2006/10/23 PHP
需要注意的几个PHP漏洞小结
2012/02/05 PHP
php+js iframe实现上传头像界面无跳转
2014/04/29 PHP
jquery 事件对象属性小结
2010/04/27 Javascript
js对列表中第一个值处理与jsp页面对列表中第一个值处理的区别详解
2013/11/05 Javascript
浅谈JavaScript字符集
2014/05/22 Javascript
jquery实现简单文字提示效果
2015/12/02 Javascript
Javascript中的神器——Promise
2017/02/08 Javascript
正则 js分转元带千分符号详解
2017/03/08 Javascript
简单实现vue验证码60秒倒计时功能
2017/10/11 Javascript
JS中移除非数字最多保留一位小数
2018/05/09 Javascript
vue-cli监听组件加载完成的方法
2018/09/07 Javascript
跟混乱的页面弹窗说再见
2019/04/11 Javascript
Angular请求防抖处理第一次请求失效问题
2019/05/17 Javascript
使用localStorage替代cookie做本地存储
2019/09/25 Javascript
vue el-table实现自定义表头
2019/12/11 Javascript
JS判断数组是否包含某元素实现方法汇总
2020/06/24 Javascript
纯python实现机器学习之kNN算法示例
2018/03/01 Python
利用Python实现Shp格式向GeoJSON的转换方法
2019/07/09 Python
Django后端接收嵌套Json数据及解析详解
2019/07/17 Python
Python3多线程版TCP端口扫描器
2019/08/31 Python
解决python cv2.imread 读取中文路径的图片返回为None的问题
2020/06/02 Python
Django利用elasticsearch(搜索引擎)实现搜索功能
2020/11/26 Python
JAKO-O德国野酷台湾站:德国首屈一指的婴幼童用品品牌
2019/01/14 全球购物
ABOUT YOU匈牙利:500个最受欢迎的时尚品牌
2019/07/19 全球购物
创意爱尔兰礼物:Creative Irish Gifts
2020/01/29 全球购物
市政施工员自我鉴定
2014/01/15 职场文书
乡镇平安建设汇报材料
2014/08/25 职场文书
2014年领导班子工作总结
2014/12/11 职场文书
杭白菊导游词
2015/02/10 职场文书
2016党性教育学习心得体会
2016/01/21 职场文书
承诺书怎么写 ?
2019/04/16 职场文书
不要在HTML中滥用div
2021/05/08 HTML / CSS
SQL 窗口函数实现高效分页查询的案例分析
2021/05/21 SQL Server
Windows Server 2019 域控制器安装图文教程
2022/04/28 Servers