1.首先介绍下python的对象引用

1)Python中不存在传值调用,一切传递的都是对象引用,也可以认为是传址调用。即Python不允许程序员选择采用传值或传引用。Python参数传递采用的是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数参数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于通过"传值"来传递对象。
2)当复制列表或字典时,就复制了对象列表的引用,如果改变引用的值,则修改了原始的参数。
3)为了简化内存管理,Python通过引用计数机制实现自动垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。

2. 可变对象与不可变对象的概念与分类

Python在heap中分配的对象分成2类:

不可变对象(immutable object):Number(int、float、bool、complex)、String、Tuple. 采用等效于“传引用”的方式。

可变对象(mutable object):List、dictionary.采用等效于“传值”的方式。

Python的数据类型和c不太一样,有一种分类标准,可变(mutable)/不可变(immutable).
我理解的可变,就是在内存中的那块内容(value)是否可以被改变。如果是不可变的,在对对象本身操作的时候,必须在内存的另外地方再申请一块区域(因为老区域#不可变#),老的区域就丢弃了(如果还有其他ref,则ref数字减1,类似unix下的hard-link)。如果是可变的,对对象操作的时候,不需要再在其他地方申请内存,只需要在此对象后面连续申请(+/-)即可,也就是它的address会保持不变,但区域会变长或者变短。

#!/usr/bin/evn python
# -*- coding:utf-8 -*-
# Author: antcolonies list1 = [1, 2, 3]
list2 = list1
list3 = list1
print('list1=', list1, '\nlist2=', list2, '\nlist3=', list3)
print('id(list1)=', id(list1), '\nid(list2)=', id(list2), '\nid(list3)=', id(list3))
'''
list1= [1, 2, 3]
list2= [1, 2, 3]
list3= [1, 2, 3]
id(list1)= 35456648
id(list2)= 35456648
id(list3)= 35456648
''' list2 = list2 + [4] # 不可变类型操作
print('list1=', list1, '\nlist2=', list2, '\nlist3=', list3)
print('id(list1)=', id(list1), '\nid(list2)=', id(list2), '\nid(list3)=', id(list3))
'''
list1= [1, 2, 3]
list2= [1, 2, 3, 4]
list3= [1, 2, 3]
id(list1)= 35456648
id(list2)= 35455304
id(list3)= 35456648
''' '''
>>> var1 = 1
>>> var2 = var1
>>> var1,var2
(1, 1)
>>> id(var1),id(var2) # 地址1782298288的引用为2
(1782298288, 1782298288)
>>> var1 += 1 # 地址1782298288的引用为2-1=1
>>> var1,var2
(2, 1)
>>> id(var1),id(var2)
(1782298320, 1782298288)
>>>
''' list3 += [4] # 可变类型操作
print('list1=', list1, '\nlist2=', list2, '\nlist3=', list3)
print('id(list1)=', id(list1), '\nid(list2)=', id(list2), '\nid(list3)=', id(list3))
'''
list1= [1, 2, 3, 4]
list2= [1, 2, 3, 4]
list3= [1, 2, 3, 4]
id(list1)= 35456648
id(list2)= 35455304
id(list3)= 35456648
'''

3. del 是删除引用而不是删除对象,对象由自动垃圾回收机制(GC)删除

看这个例子:

>>> x = 1
>>> del x
>>> x
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    x
NameError: name 'x' is not defined
>>> x = ['Hello','world']
>>> y = x
>>> y
['Hello', 'world']
>>> x
['Hello', 'world']
>>> del x
>>> x
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
x
NameError: name 'x' is not defined
>>> y
['Hello', 'world']
>>>

可以看到x和y指向同一个列表,但是删除x后,y并没有受到影响。这是为什么呢?
The reason for this is that you only delete the name,not the list
itself,In fact ,there is no way to delete values in python(and you don’t
really need to because the python interpreter does it by itself
whenever you don’t use the value anymore)
 举个例子,一个数据(比如例子中的列表),就是一个盒子,我们把它赋给一个变量x,就是好像把一个标签x贴到了盒子上,然后又贴上了y,用它们来代表这个数据,但是用del删除这个变量x就像是把标有x的标签给撕了,剩下了y的标签。
再看一个例子:
shoplist = ['apple', 'mango', 'carrot', 'banana']
print ('The first item I will buy is', shoplist[0])
olditem = shoplist[0]
del shoplist[0]  #del的是引用,而不是对象
print ('I bought the',olditem)
print ('My shopping list is now', shoplist)
print(shoplist[0])
结果为:
The first item I will buy is apple
I bought the apple
My shopping list is now ['mango', 'carrot', 'banana']
mango

实例补充:

#!/usr/bin/evn python
# -*- coding:utf-8 -*-
# Author: antcolonies
'''
python中的内置方法del不同于C语言中的free和C++中的delete
(free和delete直接回收内存,当然存储于该内存的对象也就挂了)
Python都是引用,垃圾回收为GC机制
''' '''
if __name__ == '__main__':
a = 1 # 对象 1 被 变量a引用,对象1的引用计数器为1
b = a # 对象1 被变量b引用,对象1的引用计数器加1
c = a # 对象1 被变量c引用,对象1的引用计数器加1
del a # 删除变量a,解除a对1的引用,对象1的引用计数器减1
del b # 删除变量b,解除b对1的引用,对象1的引用计数器减1
print(c) # 1
''' if __name__=='__main__':
li=['one','two','three','four','five'] # 列表本身不包含数据'one','two','three','four','five',而是包含变量:li[0] li[1] li[2] li[3] li[4]
first=li[0] # 拷贝列表,也不会有数据对象的复制,而是创建新的变量引用
del li[0]
print(li) # ['two','three','four','five']
print(first) # one
list1 = li
del li
print(list1) # ['two', 'three', 'four', 'five']
# print(type(li)) # NameError: name 'li' is not defined

Python对象引用和del删除引用的更多相关文章

  1. Python中list的删除del&remove小区别

    del删除时候指定下标,remove必须指定具体的值

  2. 使用gc、objgraph干掉python内存泄露与循环引用!

    Python使用引用计数和垃圾回收来做内存管理,前面也写过一遍文章<Python内存优化>,介绍了在python中,如何profile内存使用情况,并做出相应的优化.本文介绍两个更致命的问 ...

  3. python对象引用和垃圾回收

    变量="标签" 变量a和变量b引用同一个列表: >>> a = [1, 2, 3] >>> b = a >>> a.appen ...

  4. Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)

    我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...

  5. python中的del

    python中的del,只删除变量,不删除数据,具体表现为: a=1,c=a,del a,(c=1) 和 a = [1,2,3,4,5] b= a[0] del a[0] print a ([2,3, ...

  6. python 列表构造时的引用问题

    以前老是不注意python对象引用,平时也没遇到这样的问题,昨天在这个小问题纠结了半天时间.真是TMD啊 先说明一下我的目的,我有一个包含16个元素的列表,每个元素也是一个小列表.我想每四个子列表为一 ...

  7. python学习(九)python中的变量、引用和对象的关系

    <Think In Java>中说到过"万事万物皆对象",这句话也可以用在Python中. 感觉Python中的变量有点像Javascript中的变量,是弱类型的,但是 ...

  8. 基于Python对象引用、可变性和垃圾回收详解

    基于Python对象引用.可变性和垃圾回收详解 下面小编就为大家带来一篇基于Python对象引用.可变性和垃圾回收详解.小编觉得挺不错的,现在就分享给大家,也给大家做个参考. 变量不是盒子 在示例所示 ...

  9. Python中的变量、引用、拷贝和作用域

    在Python中,变量是没有类型的,这和以往看到的大部分编辑语言都不一样.在使用变量的时候,不需要提前声明,只需要给这个变量赋值即可.但是,当用变量的时候,必须要给这个变量赋值:如果只写一个变量,而没 ...

随机推荐

  1. Mysal表类型的区别-MyISAM,InnoDB

    1/ISAM ISAM是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数.因此,ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源.I ...

  2. UISwitch的常见属性

    1.onTintColor属性:设置ON一边的背景颜色,默认是绿色. 2.tintColor属性:设置OFF一边的背景颜色,默认是灰色,发现OFF背景颜色其实也是控件”边框“颜色. 3.thumbTi ...

  3. 原型模式及C++实现

    以下是我自己学习设计模式的感想. 原型模式 学过C++的都知道拷贝构造函数,复制一个对象分为浅拷贝和深拷贝. 浅拷贝:就是给对象中的每个成员变量进行复制,就是把A1类中的变量直接赋给A2类中变量,属于 ...

  4. Modelsim设置数据以模拟波形显示

    选中希望以模拟波形显示的信号,右击选择format—>Analog(automatic) 如果你的数据是用无符号数表示一个完整的波形的,那么可能显示出来的波形样子是下面的样子,不过不要紧,这是因 ...

  5. 大数据项目中js中代码和java中代码(解决Tomcat打印日志中文乱码)

    Idea2018中集成Tomcat9导致OutPut乱码找到tomcat的安装目录,打开logging.properties文件,增加一行代码,覆盖默认设置,将日志编码格式修改为GBK.java.ut ...

  6. ASP.NET IIS 支持PUT、DELETE请求

    IIS 本身不支持PUT.DELETE请求,但可以通过一下方法修改进而达到目的 删除IIS安装的WebDav模块,选择你的项目,右边有个“模块”,双击它:找到WebDavModule,删除它(不推荐, ...

  7. C#获取手机验证码+榛子云平台

    今天给大家推荐一个简单的获取手机验证码注册+获取随机4位数 测试框架:.net4.7以上 1.榛子云注册:http://smsow.zhenzikj.com/,送一条测试短信,最低充10元即刻使用 2 ...

  8. .net core 2.1-----Sql Server数据库初体验

    刚开始接触asp.net core,在学习的过程中遇到了一些小问题,在这里记录一下! 在我们项目的开发过程中,肯定会和数据库打交道,所以我尝试了一下用asp.net core链接数据库,并读取表中的数 ...

  9. PostMan工具使用之基础篇

    PostMan工具使用之基础篇 一.什么是PostMan Postman一款非常流行的API调试工具.(其他测试工具 Jmeter.soapUI) 二.下载及安装: 1.下载: 下载地址:https: ...

  10. Lock的await/singal 和 Object的wait/notify 的区别

    在使用Lock之前,我们都使用Object 的wait和notify实现同步的.举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒. ...