7

I can't invoke the destructor of the Parent class from the destructor of the Child class. Please, check the code below:

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()

When I use super(DerivativeClass, self).__del__() in DerivativeClass.__del__() I got the following error:

Exception TypeError: 'must be type, not None' in <bound method 
DerivativeClass.__del__ of <__main__.DerivativeClass object at 0xb73a682c>> ignored

QUESTION:

Why can't I use super in the destructor of the child class while it's perfectly fine in the constructor of the child class?

Konstantin
  • 2,937
  • 10
  • 41
  • 58
  • 1
    I'm not sure of the exact reason, but note that `super(DerivativeClass, self)` returns an object of type `super`, not an instance of `BaseClass`. `__del__` probably makes some assumption about its first argument that is not valid for `super` objects. – chepner Apr 09 '14 at 20:06
  • 1
    Put a `print(DerivativeClass)` in front of `super...` and you will see what is happening. – Hyperboreus Apr 09 '14 at 20:07
  • 1
    Or add a `del instance` as last line to your code to ensure that the instance is thrown away before the class goes over the Jordan. – Hyperboreus Apr 09 '14 at 20:08
  • 4
    Odds are you don't need to use `__del__` at all. It is best to avoid it, unless you know you *really* need it. See the good answers to [this question](http://stackoverflow.com/q/865115/2096752) for details. – shx2 Apr 09 '14 at 20:10

1 Answers1

7

It seems that this happens only on runtime exit (because DerivativeClass is None).

This works fine:

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

And this works fine too:

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()

Also this:

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 ()

In snippets 1 and 3, I make sure that the instance dies before the class. In snippet 2 I circumnavigate the whole issue in quite an ugly manner.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
Hyperboreus
  • 31,997
  • 9
  • 47
  • 87
  • 1
    It makes sense, since the behavior upon exit of the program is quite unpredictable – Konstantin Apr 09 '14 at 20:15
  • 2
    +1 The common thread in all three examples is that they avoid using a global name that is (presumably) no longer in scope when the interpreter is exiting. – chepner Apr 09 '14 at 20:24