简体   繁体   中英

How to inherit from pre-existing class instance in Python?

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"

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"

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()

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM