Dynamic module import in a class hierarchy I have two python libraries, let's call them lib and extended_lib, that provide a very similar public API. To be more specific, extended_lib enriches the API of lib with new features and functionality; it also modifies the behavior of some functions that are also provided in lib (e.g. get_version()).

I have a pair of classes LibWrapper and ExtendedLibWrapper, the latter being a sub-class of the former, that dynamically load the corresponding module and save its reference within an instance variable (i.e. self._lib).

I have a class Base that inherits from LibWrapper and a class Derived that inherits from both Base and ExtendedLibWrapper. The class Base exposes the functionalities provided by lib. The class Derived inherits all these functions and exposes also the functionalities provided by extended_lib.

This setup is meant to allow Derived to inherit, without code duplication, the functionality provided by Base.

I designed the LibWrapper and ExtendedLibWrapper as an independent hierarchy of classes because there are multiple Base/Derived pairs.

Example:

#!/usr/bin/env python3

import importlib

class LibWrapper():
    def __init__(self, *args, **kwargs):
        self._lib = self.get_lib()

    def get_lib(self):
        return importlib.import_module("lib")


class ExtendedLibWrapper(LibWrapper):

    def __init__(self, *args, **kwargs):
        super(ExtendedLibWrapper, self).__init__(*args, **kwargs)

    def get_lib(self):
        return importlib.import_module("extended_lib")


class Base(LibWrapper):
    def __init__(self, *args, **kwargs):
        super(Base, self).__init__(*args, **kwargs)

    def get_version(self):
        return self._lib.get_version()

    def print_version(self):
        print("Base class:\n\t" + self.get_version())



class Derived(Base, ExtendedLibWrapper):

    def __init__(self, *args, **kwargs):
        super(Derived, self).__init__(*args, **kwargs)

    def print_version(self):
        print("Derived class:\n\t" + self.get_version())


if __name__ == '__main__':

    base = Base()
    base.print_version()

    derived = Derived()
    derived.print_version()


The output is:

~$ ./test.py
Base class:
    Lib Version
Derived class:
    Extended Lib Version


Question(s):


coming from a different software development experience (c++), I would like to ask: is this pythonic?
is there a better, more robust or easily extensible, setup?
Yes, this is definitely pythonic: implementing lib wrappers allows one to easily include additional features in wrapper classes, as a complement to pure import. So it is both concise and versatile.

As you are working with Python 3 (according to the shebang), you may use the simplified form for super():

super().__init__(*args, **kwargs)


instead of

super(ExtendedLibWrapper, self).__init__(*args, **kwargs)


It works even with multiple inheritance.