Olarn's DevBlog
Managing constructor (__init__) calls in python multiple inheritance scenario
Sorry, failed to load main article image
Bantukul Olarn
    
May 03 2018 04:08
  

Explicit calls to each base __init__ can be managed by using the following snippet.

# encoding utf8
# py 2.7 / 3.4+
from __future__ import print_function, absolute_import, division


class a(object):
    def __init__(self):
        print("a")


class b(object):
    def __init__(self):
        print("b")


class c(object):
    def __init__(self):
        print("c")


# behavior overrides from right to left
# g -> a -> b -> c
class g(a, b, c):
    def __init__(self):
        # calling every child __init__ explicitly

        print("g")
        print(self.__class__.__mro__)
        print(self.__class__.__bases__)

        # super of self is a
        super(self.__class__, self).__init__()

        # super of a is b
        super(self.__class__.__bases__[0], self).__init__()
        # same
        # super(a, self).__init__()

        # super of b is c
        super(self.__class__.__bases__[1], self).__init__()
        # same
        # super(b, self).__init__()

        # super of c object's default __init__ , since it inherited from obj
        super(self.__class__.__bases__[2], self).__init__()
        # same
        # super(c, self).__init__()


# f -> g
class f(g):
    def __init__(self):
        # overriding and skipping g's __init__
        # emulate g's __init__

        print("f")

        # g
        base_t = self.__class__.__bases__[0]
        print("f base,", base_t)

        # calling g's __init__ directly, in this case would result in infinite recursion since
        # base class order has been changed.
        # super(self.__class__, self).__init__()

        super(base_t, self).__init__()

        super(base_t.__bases__[0], self).__init__()
        super(base_t.__bases__[1], self).__init__()
        super(base_t.__bases__[2], self).__init__()


g()
f()

print(f.__mro__)
print(f.__bases__)
print(f.__name__)

Of course f's implmentation could be turn into a dedicated function for a more elegant solution where the caller only have to specify the appropriate base type.

Tags: