Create a subclass object with initialized parent object

Question:

I have a BaseEntity class, which defines a bunch (a lot) of non-required properties and has most of functionality. I extend this class in two others, which have some extra methods, as well as initialize one required property.

class BaseEntity(object):

    def __init__(self, request_url):
        self.clearAllFilters()
        super(BaseEntity, self).__init__(request_url=request_url)

    @property
    def filter1(self):
        return self.filter1

    @filter1.setter
    def filter1(self, some_value):
        self.filter1 = some_value
    ...
    def clearAllFilters(self):
        self.filter1 = None
        self.filter2 = None
        ...

    def someCommonAction1(self):
        ...

class DefinedEntity1(BaseEntity):

    def __init__(self):
        super(BaseEntity, self).__init__(request_url="someUrl1")

    def foo():
        ...

class DefinedEntity2(BaseEntity):

    def __init__(self):
         super(ConsensusSequenceApi, self).__init__(request_url="someUrl2")

    def bar(self):
        ...

What I would like is to initialize a BaseEntity object once, with all the filters specified, and then use it to create each of the DefinedEntities, i.e.

baseObject = BaseEntity(None)
baseObject.filter1 = "boo"
baseObject.filter2 = "moo"

entity1 = baseObject.create(DefinedEntity1)

Looking for pythonic ideas, since I’ve just switched from statically typed language and still trying to grasp the power of python.

Asked By: Ox.Y.Ko

||

Answers:

One way to do it:

import copy

class A(object):
    def __init__(self, sth, blah):
        self.sth = sth
        self.blah = blah

    def do_sth(self):
        print(self.sth, self.blah)

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

    def do_sth(self):
        print(self.param, self.sth, self.blah)

a = A("one", "two")
almost_b = copy.deepcopy(a)
almost_b.__class__ = B
B.__init__(almost_b, "three")
almost_b.do_sth() # it would print "three one two"

Keep in mind that Python is an extremely open language with lot of dynamic modification possibilities and it is better not to abuse them. From clean code point of view I would use just a plain old call to superconstructor.

Answered By: Radosław Łazarz

I had the same problem as the OP and was able to use the idea from Radosław Łazarz above of explicitly setting the class attribute of the object to the subclass, but without the deep copy:

class A:
    def __init__(a) : pass
    def amethod(a) : return 'aresult'

class B(A):
    def __init__(b) : pass
    def bmethod(self) : return 'bresult'

a=A()
print(f"{a} of class {a.__class__} is {''  if isinstance(a,B) else ' not'} an instance of B")

a.__class__=B # here is where the magic happens!
print(f"{a} of class {a.__class__} is {''  if isinstance(a,B) else ' not'} an instance of B")
print(f"a.amethod()={a.amethod()} a.bmethod()={a.bmethod()}")

Output:

<__main__.A object at 0x00000169F74DBE88> of class <class '__main__.A'> is  not an instance of B
<__main__.B object at 0x00000169F74DBE88> of class <class '__main__.B'> is  an instance of B
a.amethod()=aresult a.bmethod()=bresult
Answered By: IAmStan
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.