Python:不能使用super()调用父类析构函数

7
我无法在子类的析构函数中调用父类的析构函数。请查看以下代码:
class BaseClass(object):
    def __del__(self):
        print 'BaseClass->Destructor'

class DerivativeClass(BaseClass):
    def __del__(self):
        print 'DerivativeClass->Destructor'
        #Invoke destructor of the base class, it works 
        BaseClass.__del__(self)           
        #Doesn't work
        #super(DerivativeClass, self).__del__() 

instance = DerivativeClass()

当我在DerivativeClass.__del__()中使用super(DerivativeClass, self).__del__()时,我遇到了以下错误:
Exception TypeError: 'must be type, not None' in <bound method 
DerivativeClass.__del__ of <__main__.DerivativeClass object at 0xb73a682c>> ignored

问题:

为什么在子类的析构函数中不能使用super,而在子类的构造函数中却完全没有问题?


1
我不确定确切的原因,但请注意super(DerivativeClass, self)返回一个类型为super的对象,而不是BaseClass的实例。__del__可能对其第一个参数做出了一些假设,这些假设对于super对象无效。 - chepner
1
super... 前面加上 print(DerivativeClass),你就会看到发生了什么。 - Hyperboreus
1
或者在你的代码中添加 del instance 作为最后一行,以确保在类过度时实例被丢弃。 - Hyperboreus
4
很可能你根本不需要使用__del__。除非你确定真的需要它,否则最好避免使用它。有关详细信息,请参见此问题中的好答案。 - shx2
1个回答

7

看起来这只发生在运行时退出时(因为 DerivativeClassNone)。

这个是正常工作的:

class BaseClass(object):
    def __del__(self):
        print 'BaseClass->Destructor'

class DerivativeClass(BaseClass):
    def __del__(self):
        print 'DerivativeClass->Destructor'
        super(DerivativeClass, self).__del__() 

instance = DerivativeClass()
del instance

这也是有效的:

class BaseClass(object):
    def __del__(self):
        print 'BaseClass->Destructor'

class DerivativeClass(BaseClass):
    def __del__(self):
        print 'DerivativeClass->Destructor'
        super(type(self), self).__del__() 

instance = DerivativeClass()

此外还有这个:
class BaseClass(object):
    def __del__(self):
        print 'BaseClass->Destructor'

class DerivativeClass(BaseClass):
    def __del__(self):
        print 'DerivativeClass->Destructor'
        super(DerivativeClass, self).__del__() 

def someScope ():
    instance = DerivativeClass()

someScope ()

在代码段1和代码段3中,我确保实例在类之前被销毁。在代码段2中,我使用了一种相当丑陋的方式绕过了整个问题。


1
这是有道理的,因为程序退出时的行为相当不可预测。 - Konstantin
2
三个示例中的共同点是它们避免使用全局名称,当解释器退出时,该名称(可能)不再在作用域内。 - chepner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接