python 的__del__删除器方法

遇到了python关于del的小问题,又引发了一些问题,就简单的记录下,如果有不同意见,欢迎一起讨论~



python类似java是有垃圾回收机制的语言,所以我们不需要像c++一样通过析构函数来手动释放内存,

但是python也同样提供了__del__释放方法。当一个对象的引用计数为0时,会被自动调用,那么先来说说

引用计数吧。

1.引用计数

#!/usr/bin/env python
#coding:UTF-8

import sys

class MyClass(object):
    def __init__(self):
        print('i am __init__ function')

    def __del__(self):
        print('i am __del__ function')


if __name__ == '__main__':
    m1 = MyClass()
    m2 = m1
    print(sys.getrefcount(m1))

结果如下图:


结果很让人吃惊吧,只有两个实例,为什么引用计数是3 ? 

都知道python是一门脚本语言,解释型语言,但是不知道大家有没有注意python其实也是有编译过程的。

.pyc文件就是个很好的证明。可以去/usr/lib/python看看

所以说的细致一点python是一门先编译后解释的语言,编译指的是编译成为字节码,然后然逐行解释字节码。

平时解释器帮我们做好了而已,你可能会说上面的代码怎么看不见.pyc文件呢,你把函数单独成一个.py文件

然后import导入后编译就可以看见了。其实.pyc文件只是编译后的 PyCodeObject存储在硬盘上的表现而已。

编译产生的真正的结果是PyCodeObject

过程.py ->编译 -> PyCodeObject ->解释(虚拟机执行)

现在说引用计数,绕了个弯,其实也不算,因为引用计数的值不对就是因为python的编译过程。


详情可参考http://blog.csdn.net/balabalamerobert/article/details/1649490


2.__del__


前面说了python的引用计数为0时会自动回收对象,所以一般是不推荐我们使用python中的__del__删除方法的

我在自己使用__del__过程中就遇到了一个问题,还是看代码:

定义了两个类,一个基类MyClass有名字和电话等信息,派生类DerClass添加了地址,每个类都有一个attribute属性

glb和der_glb。

#!/usr/bin/env python
#coding:UTF-8

class MyClass(object):
    glb = 100                #global variable
    def __init__(self, nm, ph):
        self.name = nm
        self.phone = ph

class DerClass(MyClass):
    der_glb = 200               #global variable
    def __init__(self, nm, ph, addr):
        super.__init__(nm, ph)                  #python3
        self.address = addr

    def __del__(self):
        #del self.__class__.der_glb
        del self.der_glb
        print 'del der_glb'

if __name__ == '__main__':
    m1 = MyClass('wwh', '123')
    m2 = DerClass('wwh', '456', 'xian')

主要看下del函数,我在del函数中自己调用了del self.der_glb来删除这个所有类共用的变量

(python中类内定义的变量所有实例共用)

结果报错了


但是我改为del self.__class__.der_glb却正确了

这是什么原因呢

前面说了python中类内定义的变量所有实例共用,那么每个实例在结束后也就是自己的引用计数为0时都会被调用del

也就是说每个实例都del了一遍只有一份的der_glb变量,当然是不对的

那么为什么加上__class__就正确了呢

python的内存模型应该是我们定义了一个类后,这个类的模板module也会在内存中存储一份(id(Der_class)可证明),毕竟它还有所有实例需要用的变量等等。

所以__class__含义应该是获取到内存中这个module的地址,然后取得module的der_glb,删除它。

删除它后我们当然不能使用它了。

类似python的delattr(obj, attr)删除类的属性一样

在我按照上面所说的进行修改后,del self.__class__.der_glb,运行成功,并且再次定义类的实例时访问der_glb属性报错,报错结果如下:


可见在del der_glb后,再次使用der_glb显示has no attibute 'der_glb',证明前面我所说的是正确的,该属性已经被删除

说明一下python中的der_glb类似c++中的static变量,所有实例被共用,但是在python中被称为该类的属性attribute。


虽然python很好用,但是也需要搞清楚一些原理 ^_^






  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏天的技术博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值