Python的内存管理是基于垃圾回收器机制

转载:http://bbs.csdn.net/topics/340133602

Python的内存管理是基于垃圾回收器机制的,所以并不像C++那样在超出对象作用域的时候自动调用其析构函数,而是等到引用计数为0的时候才会调用__del__,而这个时机是无法控制的。所以在Python中不能将释放紧迫资源的机会依赖于__del__函数,最好是手动释放。

这里我加上gc来显示垃圾回收的时机:

import gc

class Person:
    count=0

    def __init__(self,name):
        self.name=name
        self.myname=name # 必须指明self.对象变量名,否则视为函数局部变量
        Person.count+=1 # 必须用类名.类变量名
        print 'Init! name=%s, count=' % name,Person.count

    def __del__(self):
        Person.count-=1
        print 'Del name=%s, count=' % self.myname,Person.count

gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_LEAK)
swaroop = Person('Swaroop')
swaroo1p = Person('Swaro2op') # swaroo2p不出错,swaroo1p出错。郁闷啊
kalam = Person('Abdul Kalam')
用swaroo1p时, 结果:
Init! name=Swaroop, count= 1
Init! name=Swaro2op, count= 2
Init! name=Abdul Kalam, count= 3
Del name=Abdul Kalam, count= 2
Del name=Swaroop, count= 1
gc: collecting generation 2...
gc: objects in each generation: 51 4673 0
gc: done, 0.0010s elapsed.
Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound method Person.__del__ of <__main__.Person instance at 0x0262D260>> ignored

可以看到在调用Swaroo1p.__del__之前就已经运行了垃圾回收,所以当调用Swaroo1p.__del__的时候,Person已经是None了,对None访问count当然会出错。

现在改成Swaro2op, 结果为:
Init! name=Swaroop, count= 1
Init! name=Swaro2op, count= 2
Init! name=Abdul Kalam, count= 3
Del name=Swaro2op, count= 2
Del name=Abdul Kalam, count= 1
Del name=Swaroop, count= 0
gc: collecting generation 2...
gc: objects in each generation: 51 4673 0
gc: done, 0.0000s elapsed.
这次直到调用了swaroo2p.__del__才运行垃圾回收。

不过仍然困惑我的是,到底为什么改了名字就会改变垃圾回收的时机?


使用域变量时,可以通过self的__class__域来引用
与python的内存回收按照字典先后顺序有关

把Person.count换成self.__class__.count,将不会出错!

原因可能是在idel模式下编译时导致的引用计数计算顺序异常,可以尝试把程序写成文件.py形式来导入,生成.pyc形式的。


我查了一下网上有类似问题:http://markmail.org/message/dod55fek3bt36axw(这个可能要轻功才能看)

1、错误的真正根源在_PyModule_Clear中
2、Python在销毁运行时环境时,其顺序并非是由dir()显示的那个顺序。因为如果把你的两个变量名由lzh, lds改为a, b,则就没有异常产生了。

我加上了del,看起来可以了:
print dir()
swaroop = Person('Swaroop')
swaroo1p = Person('Swaro2op') # 囧ing
kalam = Person('Abdul Kalam')
print dir()

del swaroop
print dir()
del swaroo1p
print dir()
del kalam
print dir()

说实话《简明 Python 教程》上这样教也不好,虽然说了__del__的作用,但怎么用没指明,初学者郁闷。
晚上回来结贴给分。目前还有问题就是释放类和实例的顺序问题,python不至于在释放所有实例之前先把类本身释放了吧。


尽可能避免使用__del__和类空间的共用变量。

官方文档:http://docs.python.org/reference/datamodel.html#object.__del__


Warning
Due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值