5

I have a class Parent:

class Parent:
    def __init__(self, foo):
        self.foo = foo

I then have another class Child which extends Parent. But I want Child to take a pre-existing instance of parent and use this as the parent to inherit from (instead of creating a new instance of Parent with the same constructor parameters).

class Child(Parent):
    def __init__(self, parent_instance):
        """ Do something with parent_instance to set this as the parent instance """

    def get_foo(self):
        return self.foo

Then I would ideally be able to do:

p = Parent("bar")
c = Child(p)

print(c.get_foo()) # prints "bar"
4
  • self.parent = parent_instance and then self.parent.foo or something similar? Commented Jun 28, 2020 at 16:47
  • @KlausD. Could do, but would prefer proper inheritance, if possible. At the moment your suggestion is what I am doing. Commented Jun 28, 2020 at 16:49
  • This is a duplicate of the ancient question: stackoverflow.com/questions/1081253/… The suggestions still make sense :) Commented Jun 28, 2020 at 16:54
  • In your example "bar" can't get anything else than an instance attribute. But you can only inherit class attributes. Commented Jun 28, 2020 at 16:56

4 Answers 4

8

You could copy the content of the parents's __dict__ to the child's. You can use vars() builtin function to do so, and the dictionary's update() method.

class Child(Parent):
    def __init__(self, parent_instance):
        vars(self).update(vars(parent_instance))

    def get_foo(self):
        return self.foo


p = Parent("bar")
c = Child(p)

print(c.get_foo())
# prints "bar"
Sign up to request clarification or add additional context in comments.

2 Comments

Are there any disadvantages to this?
Not really, unless you don't want the child to have some specifics attributes that the parent has.
3

You can use your own constructor - provide a classmethod that takes an instance of a parent.

class Parent:
    def __init__(self, foo):
        self.foo = foo

class Child(Parent):
    def get_foo(self):
        return self.foo

    @classmethod
    def from_parent(cls, parent_instance):
        return cls(parent_instance.foo)


p = Parent('bar')
c = Child.from_parent(p)
c.get_foo()

2 Comments

But this will create a new instance of Parent, right? I do not want to re-instantiate.
If foo attribute is changed in the parent class, the link will be break in child. (child will keep the older reference) e.g : p = Parent("foo"); c = Child.from_parent(p); p.foo = "spam"; assert c.foo == "foo"
0

I'm not sure inheritance is the right solution here as it breaks the LSP in the __init__ method.

Maybe parents and children just share a common interface. I'd prefer something like (python3.8):

from typing import Protocol
    
class FoeAware(Protocol):
    @property
    def foe(self):
        ...
 
class Parent:
    def __init__(self, foe):
        self._foe = foe
   
    @property
    def foe(self):
        return self._foe

class Child:
    def __init__(self, parent: FoeAware):
        self.parent = parent

    @property
    def foe(self):
        return self.parent.foe

p = Parent("bar")
c = Child(p)
c.foe  # bar

The key point is that it takes advantage of polymorphism with a common interface FoeAware, which is preferable to an inheritance tree.

Comments

0

Using getattr() to fetch the attribute from the parent instance

class Parent: 
    def __init__(self, foo): 
        self.foo = foo 

class Child(Parent): 
    def __init__(self, parent_instance): 
        self.parent_instance = parent_instance
    
    def get_foo(self): 
        return self.foo 
        
    def __getattr__(self, attr):
        return getattr(self.parent_instance, attr)

par = Parent("bar") 
ch = Child(par)
print(ch.get_foo())
#prints bar

3 Comments

I think this will create a new instance of Parent though - I want to use the already existing instance of Parent that has been passed in.
This will crash if you attach another attribute in parent instance that is not in the init signature. Or if instance attribute is renamed, e.g self._foo = foo
I've updated my code to work without creating another instance

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.