Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python inheritance: pass all arguments from base to super class

I am not quite used to class inheritance in Python yet. All I want to do is simply pass all arguments from my base class to the super class when it is created:

class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def do(self):
        c = self.a + self.b
        return B(c=c)

class B(A):
    def __init__(self, c):
        self.c = c

my_A = A(a=1, b=2)
my_B = my_A.do()
print(my_B.c)

This works as expected. However, what I want is to also be able to call the arguments a and b from the x2 instance of the class my_B, so that I can directly write my_B.a for instance. I know this is done with super() like this:

class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def do(self):
        c = self.a + self.b
        return B(a=self.a, b=self.b, c=c)

class B(A):
    def __init__(self, a, b, c):
        super(B, self).__init__(a=a, b=b)
        self.c = c

my_A = A(a=1, b=2)
my_B = my_A.do()
print(my_B.a)
print(my_B.b)

However, I don't want to explicitly write all arguments of A when I create the instance of B. Is there a way to automatically pass all arguments from class A to class B?

like image 925
HansSnah Avatar asked Sep 04 '25 17:09

HansSnah


2 Answers

Based on your comment, you could do something like this:

class B(A):
    def __init__(self, c, an_a): 
        super(B, self).__init__(an_a.a, an_a.b)
        self.c = c

You may instead prefer to keep your current constructor and add a from_a static method:

class B(A):
    def __init__(self, c, a, b):  # note order
        super(B, self).__init__(a=a, b=b)
        self.c = c

    @staticmethod
    def from_a(c, an_a):
        return B(c, an_a.a, an_a.b)

Finally, if you don't want to type out all of those parameters, you can add an args() method to A and then use the collection unpacking function syntax:

class A:
    ...
    def args(self):
        return (self.a, self.b)

class B(A):
    def __init__(self, c, *args):        # Note *args
        super(B, self).__init__(*args)
        self.c = c

    @staticmethod
    def from_a(c, an_a):
        return B(c, *an_a.args())

Now B's constructor takes the parameter special to B, followed by any number of parameters which just get passed to A's constructor. This allows you to do the tuple unpacking when calling the constructor, instead of listing everything out manually.

like image 123
Claudiu Avatar answered Sep 07 '25 18:09

Claudiu


Ok, thanks for your comments. I have come up with this solution:

class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def do(self):
        c = self.a + self.b
        return B(self, c)

class B:
    def __init__(self, base, c):
        self.base = base
        self.c = c

my_A = A(a=1, b=2)
my_B = my_A.do()
print(my_B.base.a)
print(my_B.base.b)
print(my_B.c)

This removes the inheritance of class B and makes the code slightly less readable, but I guess it will do, right? 😊

like image 35
HansSnah Avatar answered Sep 07 '25 17:09

HansSnah