calling destructor in python multiply-inherited class

Duncan Booth me at privacy.net
Thu May 20 07:45:12 EDT 2004


rajorshi at fastmail.fm (Rajorshi) wrote in 
news:85b5e3f8.0405200259.468161f3 at posting.google.com:

> In the destructor of the derived class, if I write something like this
> 
> def __del__(self):
>    for b in self.__class__.__bases__:
>       b.__del__(self)
> 
> then its working fine, but if I am doing something straightforward
> like
> 
> def __del__(self):
>     Base1.__del__(self)
>     Base2.__del__(self)
> 
> Its giving an error like :
> Exception exceptions.AttributeError: "'NoneType' object has no
> attribute '__del__'" in <bound method Derv.__del__ of <__main__.Derv
> instance at 0x8187484>> ignored
> 
> Obviously I'm doing something wrong ! Any pointers ??
> 

I guess this error occurs when your program is exiting. When a Python 
program terminates the global variables in each module are set to None. The 
order in which this happens it undefined, so when your __del__ method gets 
called the global Base1, or maybe Base2, has already been cleared. The base 
classes still exist, so you can access them through your class, but the 
names they used will have been rebound.

A reasonable conclusion from this is:
A __del__ method must never access *any* global variables unless it is 
prepared to handle the consequences of the global not existing.

Next question, do you really need to use __del__? Remember that Python will 
not always call the __del__ method at the time you expect, and that the 
behaviour will vary on different Python implementations. Also the existence 
of a __del__ method is sufficient to prevent your object ever being 
released from a cycle by the garbage collector. If you need explicit tidy 
up, use a dispose pattern instead of depending on __del__.

There is very little that you can usefully do inside a __del__ method. 
Deleting contained objects is pointless (it happens automatically without 
you doing it in __del__). Closing a file should be done explicitly when you 
are finished with it because if you try to do it in __del__ and the call to 
__del__ is delayed you will get unexpected problems.

If you really need to call __del__ on more than one base class, use the 
super() builtin to do it.



More information about the Python-list mailing list