1 个回答

7

这个问题是因为类里面有循环引用,也就是说它们会互相指向自己。所以当这些类被删除的时候,它们不容易被清理掉,因此元类的 __del__ 方法不会被调用。

我可以在 Pypy 的 Python 实现中触发这个方法被调用,但在 cpython 中,无论是 2.6 还是 3.2 都不行。即使要触发它,我还得手动调用垃圾回收器——在程序退出时,Python 环境通常会出现很多不一致的情况,因此 __del__ 方法在内部信息足够的情况下被调用的机会非常小。

下面是我在 Pypy 中触发类的 __del__ 方法的会话记录:

 ~]$ pypy                                                                                       
Python 2.5.2 (78826, Nov 29 2010, 00:18:05)                                                                       
[PyPy 1.4.0] on linux2                                                                                            
Type "help", "copyright", "credits" or "license" for more information.                                            
And now for something completely different: ``sorry, I'll teach the cactus how                                    
to swim later''                                                                                                   
>>>> import gc
>>>> class Meta(type):         
....    def __del__(cls):                          
....       print ("Arghh!!")                                              
....                                                                      
>>>> class A(object):                                                                     
....   __metaclass__ = Meta                                                                                     
....                                                                                                                                                                                                                
>>>> del A                                                                                                        
>>>> gc.collect()                                                                                                 
Arghh!!                                                                                                           
0                                                                                                                 
>>>>

2022 - 从 Python 3.11 a06 开始,如果在删除所有指向类的引用后调用 gc.collect(),那么在 cPython 中元类的 __del__ 方法就能正常工作,就像在这个例子中 Pypy 的表现一样。

撰写回答