0

Say I have a class A that holds some basic attributes, ie

class A: 
    def __init__(self,name,value,):
        self.name = name
        self.value = value

I want to make a sub-class B that has all the properties of A, but also includes additional methods, like

class B(A):
    def __init__(self,instance_of_A):
        # ???        
    def add_to_value(self,x):
        return self.value + x

Eventually, I want to do something like

a = A('my_name',3)
b = B(a)
c = b.add_to_value(2) # c is 5
print(b.name) # should print 'my_name'

Is there a way to do this without explicitly taking every attribute of a and giving it to b when b is created?

Dan
  • 25
  • 4
  • 1
    Does this answer your question? [How to invoke the super constructor in Python?](https://stackoverflow.com/questions/2399307/how-to-invoke-the-super-constructor-in-python) – smac89 Oct 08 '21 at 18:56
  • 1
    Please read more about inheritance starting here [Simple python inheritance](https://stackoverflow.com/questions/6381590/simple-python-inheritance). – BcK Oct 08 '21 at 18:57
  • 1
    You can do something like `vars(self).update(vars(instance_of_A))` if it is a non-slotted class – juanpa.arrivillaga Oct 08 '21 at 19:07
  • 1
    Why do you want to use an existing `A` instance to create the `B`? Why not just write the constructor so that it takes in the same information, and calls `super`? (Or if there is no additional construction work to do, just skip `__init__` and thus use the base constructor?) – Karl Knechtel Oct 08 '21 at 19:18
  • Thanks @juanpa.arrivillaga, that's what I was looking for. I'll use that and `[setattr(self, method, getattr(a,method)) for method in methods]` with `methods = [attr for attr in dir(a) if callable(getattr(a, attr)) and attr.startswith('__') is False]` to give `b` the methods of `a` as well. – Dan Oct 08 '21 at 19:35
  • @Dan no, dont do that, **use inheritance** – juanpa.arrivillaga Oct 08 '21 at 19:50
  • Also, *don't use list comprehensions for side effects*: `[setattr(self, method, getattr(a,method)) for method in methods]` – juanpa.arrivillaga Oct 08 '21 at 19:52
  • Why are you using inheritance *and* composition? That doesn't make any sense to me, though I'm not an expert on OOP design. If composition isn't required, then the answer is dead-simple: don't define `B.__init__()`. – wjandrea Oct 08 '21 at 20:57

2 Answers2

0

You're keeping __init__() function of B empty, that might give error. To keep it empty, write a pass statement in it. If you want to keep it, then __init__() of B must also have the parameters of A so that those value can be forwarded to A while calling. If at all you want to keep it empty, better not to write it then, directly __init__() of A will be called when object of B is created. While creating an object of B, you don't need to write B(a), directly pass the parameters of A and you'll get the desired output.

b = B('my_name', 3)
c = b.add_to_value(2) # c is 5
wjandrea
  • 28,235
  • 9
  • 60
  • 81
0

This is how I would go about this:

class B(A):
    def __init__(self, name, value, extra_attribute_only_for_B):
        super().__init__(name, value) # Initializes attributes of base class
        self.extra_var = extra_attribute_only_for_B # Can give B more attributes

    def add_to_value(self,x):
        return self.value + x

b = B('my_name',3)
c = b.add_to_value(2)
print(b.name)
print(c)

Output:

my_name
5

Since B is subclassing A you can call A's __init__() to initialize the inherited attributes, and also give B further new attributes that A won't have (I have included an example)

Shubham
  • 1,310
  • 4
  • 13