Assume that we have an object k of type class A. We defined a second class B(A). What is the best practice to "convert" object k to class B and preserve all data in k?
-
2In what way are you looking to convert from one to the other? Do you wish to keep all of the member variables of the class B object, but use the parent class A's set of methods?BrainCore– BrainCore2010-01-28 09:04:41 +00:00Commented Jan 28, 2010 at 9:04
-
3Is this Pretty Poor Polymorphism? Are A and B subclasses of a common superclass? If so, this is the wrong thing to do? Do you wish that A had the same methods as B? This is done through multiple-inheritance. Please explain why you think you need this because -- in Python -- you're doing it wrong if you think you need casting or type conversion.S.Lott– S.Lott2010-01-28 11:52:35 +00:00Commented Jan 28, 2010 at 11:52
-
Also really curious about your use case. Is this just for fun, or have you found this to be a better way of adressing some problem, other than with the help of classical polymorphism?vlad-ardelean– vlad-ardelean2015-01-04 01:04:56 +00:00Commented Jan 4, 2015 at 1:04
-
Depending on your problem, one of these two methods for achieving a similar result might be suitable, without feeling like a hack.Beetle– Beetle2015-01-13 16:45:06 +00:00Commented Jan 13, 2015 at 16:45
3 Answers
This does the "class conversion" but it is subject to collateral damage. Creating another object and replacing its __dict__ as BrainCore posted would be safer - but this code does what you asked, with no new object being created.
class A(object):
pass
class B(A):
def __add__(self, other):
return self.value + other
a = A()
a.value = 5
a.__class__ = B
print a + 10
Comments
a = A() # parent class
b = B() # subclass
b.value = 3 # random setting of values
a.__dict__ = b.__dict__ # give object a b's values
# now proceed to use object a
Would this satisfy your use case? Note: Only the instance variables of b will be accessible from object a, not class B's class variables. Also, modifying variables in a will modify the variable in b, unless you do a deepcopy:
import copy
a.__dict__ = copy.deepcopy(b.__dict__)
2 Comments
a and b now both share the same __dict__, setting a.value changes b.value too.class A:
def __init__(self, a, b):
self.a = a
self.b = b
class B(A):
def __init__(self, parent_instance, c):
# initiate the parent class with all the arguments coming from
# parent class __dict__
super().__init__(*tuple(parent_instance.__dict__.values()))
self.c = c
a_instance = A(1, 2)
b_instance = B(a_instance, 7)
print(b_instance.a + b_instance.b + b_instance.c)
>> 10
Or you could have a sperate function for this:
def class_converter(convert_to, parent_instance):
return convert_to(*tuple(parent_instance.__dict__.values()))
class B(A):
def __init__(self, *args):
super().__init__(*args)
self.c = 5
But using the 2nd method, I wasn't able to figure out how to pass additional values