最近学习《Python参考手册》学到Class部分,遇到了类的构造析构部分的问题: 1、什么时候构造? 复制代码 代码如下: __priValue = 0 # 会自动变形为"_类名__priValue"的成员变量 3、由于Python的特殊性,全局成员变量是共享的,所以类的实例不会为它专门分配内容空间,类似于static,具体使用参看下面的例子。 测试1: 复制代码 代码如下: # encoding:utf8 class NewClass(object): aa = NewClass("Hello") print "Over" 调试运行: 复制代码 代码如下: Hello 1 World 2 aaaa 3 Over DeException l Hello 2 AttributeError: "'NoneType' object has no attribute 'num_count'" in <bound method NewClass.__del__ of <__main__.NewClass object at 0x01AF18D0>> ignored Exception AttributeError: "'NoneType' object has no attribute 'num_count'" in <bound method NewClass.__del__ of <__main__.NewClass object at 0x01AF1970>> ignored 我们发现,num_count 是全局的,当每创建一个实例,__init__()被调用,num_count 的值增一,当程序结束后,所有的实例会被析构,即调用__del__() 但是此时引发了异常。查看异常为 “NoneType” 即 析构时NewClass 已经被垃圾回收,所以会产生这样的异常。 但是,疑问来了?为什么会这样?按照C/C++等语言的经验,不应该这样啊!经过查找资料,发现: Python的垃圾回收过程与常用语言的不一样,Python按照字典顺序进行垃圾回收,而不是按照创建顺序进行。所以当系统进行回收资源时,会按照类名A-Za-z的顺序,依次进行,我们无法掌控这里的流程。 明白这些,我们做如下尝试: 复制代码 代码如下: # encoding:utf8 class NewClass(object): aa = NewClass("Hello") del aa print "Over" 调试输出: 复制代码 代码如下: Hello 1 World 2 aaaa 3 Del Hello 2 Del World 1 Del aaaa 0 Over OK,一切按照我们预料的顺序发生。 SO,继续查找,我们还可以通过self.__class__访问到类本身,然后再访问自身的共享成员变量,即 self.__class__.num_count , 将类中的NewClass.num_count替换为self.__class__.num_count 编译运行,如下: 复制代码 代码如下: # encoding:utf8 class NewClass(object): aa = NewClass("Hello") print "Over" 结果: 复制代码 代码如下: Hello 1 World 2 aaaa 3 Over Del Hello 2 Del World 1 Del aaaa 0 Perfect!我们完美地处理了这个问题! PS: 书上又提到了一些问题,在这里作补充(仅作为参考): __new__()是唯一在实例创建之前执行的方法,一般用在定义元类时使用。 del xxx 不会主动调用__del__方法,只有引用计数==0时,__del__()才会被执行,并且定义了__del_()的实例无法被Python的循环垃圾收集器收集,所以尽量不要自定义__del__()。一般情况下,__del__() 不会破坏垃圾处理器。 实验中发现垃圾回收自动调用了__del__, 这与书上所说又不符,不知是什么原因,需要继续学习。 |
|