DEV Community

Kevin Albertson
Kevin Albertson

Posted on

Order of __init__ and __del__

The order of calls to __del__ surprised me. In Python:

class A:
    def __init__ (self):
        print ("A.__init__")
    def __del__ (self):
        print("A.__del__")

class B:
    def __init__ (self):
        print ("B.__init__")
    def __del__ (self):
        print ("B.__del__")

def fn():
    a = A()
    b = B()

fn ()
"""
Produces this output:
A.__init__
B.__init__
A.__del__
B.__del__
"""
Enter fullscreen mode Exit fullscreen mode

I expected __del__ to be called in reverse order (ABBA). The reverse order matches C++ behavior.

An alternative to guarantee order is __enter__ and __exit__ and use of the with block:

class A:
    def __enter__ (self):
        print ("A.__enter__")
    def __exit__ (self, exc_type, exc_val, exc_tb):
        print("A.__exit__")

class B:
    def __enter__ (self):
        print ("B.__enter__")
    def __exit__ (self, exc_type, exc_val, exc_tb):
        print ("B.__exit__")

def fn():
    with A() as a, B() as b:
        pass

fn ()

"""
Produces this output:
A.__enter__
B.__enter__
B.__exit__
A.__exit__
"""
Enter fullscreen mode Exit fullscreen mode

The standard guarantees the order:

With more than one item, the context managers are processed as if multiple with statements were nested:

with A() as a, B() as b:
    SUITE

is semantically equivalent to:

with A() as a:
    with B() as b:
        SUITE

Top comments (0)