'How to overwrite default value of parameter in python __init__ method from class with two levels of inheritance:

I need to overwrite the default parameter value of __init__ method of a class that is on a three-party model which inherits from another three-party module, but I don´t want to copy all of the two levels of __init__ parameters to my class just to do that, I think this is not a good practice, for a lot of reasons.

a simple sample code will be this:

from typing import Any, Callable



class A:
"class A from module 1"
    def __init__(self, param_A_1: Any, param_A_2: Any) -> None:
        self.param_A_1 = param_A_1
        self.param_A_2 = param_A_2


def func() -> str:
    return "Hi there!"

class B(A):
"class B from module 2"
    def __init__(
        self,
        param_A_1: Any,
        param_A_2: Any,
        paran_B_1: Any,
        param_B_2: Any,
        param_to_overwrite: Callable = func, 
    ) -> None:
        super().__init__(param_A_1, param_A_2)
        self.paran_B_1 = paran_B_1
        self.param_B_2 = param_B_2
        self.param_to_overwrite = param_to_overwrite


def my_func() -> str:
    return "hello"


class C(B):
"my class"
    def __init__(
        self,
        param_A_1: Any,
        param_A_2: Any,
        paran_B_1: Any,
        param_B_2: Any,
        param_to_overwrite: Callable = my_func,
    ) -> None:
        super().__init__(self, param_A_1, param_A_2, paran_B_1, param_B_2, param_to_overwrite)

In the example code. class A and class B are three-party modules and class C is mine. this is a working example, but I'm looking for a way to avoid the repetition of the __init__ method thinking on that the originals classes have a lot more parameter

I think this can be solved with a metaclass but I don't know how to do it.



Solution 1:[1]

This seems like a good use case for *args:

class C(B):
    def __init__(
        self,
        *args,
        param_to_overwrite: Callable = my_func,
        **kwargs,
    ) -> None:
        super().__init__(*args, param_to_overwrite=param_to_overwrite, **kwargs)


assert C("A1", "A2", "B1", "B2").param_to_overwrite() == "hello"
assert C(param_A_1="A1", param_A_2="A2", paran_B_1="B1", param_B_2="B2").param_to_overwrite() == "hello"

The main downside of this compared to enumerating the args explicitly is that it's not type-safe, but since the original code is annotated with Any I assume that's not a concern.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1