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很好用,但是也需要搞清楚一些原理 ^_^

时间: 2024-10-12 20:01:54

python 的__del__删除器方法的相关文章

python 原生列表删除元素方法总结

一.列表方法remove(),按值删除,删除首个符合的元素 二.列表方法pop(),按索引删除,默认删除最后一个元素 三.del函数,删除某个变量或者某些元素 原文地址:https://www.cnblogs.com/dearL/p/9545402.html

【python初级】010-构造方法,属性和迭代器

构造方法,属性和迭代器 目录: -------------构造方法 1.构造方法的基本使用 2.重写一般方法和特殊的构造方法 3.绑定的超类构造方法 4.调用为绑定的超类来构造方法 5.使用super函数 6.成员访问 7.基本的序列和映射规则 8.子类化列表,字典和字符串 -------------属性 -------------迭代器 一:构造方法 在python的心版本中,会有一些特性(比如属性和super函数)不会再老式的类上起作用,为了确保使用的类是新型的,应该把赋值语句metacla

python学习笔记--装饰器

1.首先是一个很无聊的函数,实现了两个数的加法运算: def f(x,y): print x+y f(2,3) 输出结果也ok 5 2.可是这时候我们感觉输出结果太单一了点,想让代码的输出多一点看起来不这么单调: def showInfo(fun): def wrap(x,y): print "The function before" func(x,y) print "The function after" return wrap def f(x,y): print

【python】-- 类的装饰器方法、特殊成员方法

装饰器方法 类的另外的特性,装饰器方法:静态方法(staticmethod).类方法(classmethod).属性方法(property) 一.静态方法 在方法名前加上@staticmethod装饰器,表示此方法为静态方法 class Dog(object): def __init__(self,name): self.name = name @staticmethod #在方法前加上staticmethod 装饰器定义静态方法 def eat(): print("dog is eating&

033.Python的__del__析构方法he__call__方法

一 __del__ 魔术方法(析构方法) 1.1 介绍 触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候] 功能:对象使用完毕后资源回收 参数:一个self接受对象 返回值:无 1.2 页面执行完毕回收所有变量 class Plane(): def __init__(self,name): self.name = name def fly(self): print ("我的飞机是{}飞的很快".format(self.name)) de

【智能指针的延伸】两种定制删除器的实现方法

所谓定制删除器,就是向目标模板提供一个可以自由选择析构的接口,这样做的好处就是可以使智能指针模板不再只能单独管理内存,我们还可以用它管理文件指针之类的东西.其实现方法有两种,这里我们以share指针为例.   1.传递一个类的模板参数并给出缺省值,模板中将该类设定为成员变量,通过该类(删除类)的实例化,调用类中所存的删除方法进行删除. 代码如下: #include<iostream> template <class T> struct Del { void operator ()(

实战c++中的智能指针unique_ptr系列-- unique_ptr的get_deleter方法(自定义删除器)

unique_ptr的成员函数在上一篇博客中几乎全部涵盖,其实还有一个很有踢掉,即std::unique_ptr::get_deleter 字面已经很明显了,就获得deleter: Returns the stored deleter The stored deleter is a callable object. A functional call to this object with a single argument of member type pointer is expected

python装饰器方法

前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看django官网,忽然发现,装饰器用法并不是django框架提供的,而是python的一种语法,真心汗一个,自以为python用的很熟了,看来是井底之蛙! 恰逢周末,静下心来了解一下python的装饰器方法. 谈到代码里的装饰器,很自然的想到了设计模式中的装饰器模式,为了防止再次张冠李戴,特意翻了翻设计模

类的装饰器方法、特殊成员方法

https://www.cnblogs.com/Keep-Ambition/p/7296492.html 装饰器方法 类的另外的特性,装饰器方法:静态方法(staticmethod).类方法(classmethod).属性方法(property) 一.静态方法 在方法名前加上@staticmethod装饰器,表示此方法为静态方法 class Dog(object): def __init__(self,name): self.name = name @staticmethod #在方法前加上st