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.
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.
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
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.
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.
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