tags:

views:

123

answers:

3

Greetings,

let assume that we have a 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?

Thanks,

Shakov

+1  A: 
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__)
BrainCore
Actually, no variables will be copied. Since `a` and `b` now both share the same `__dict__`, setting `a.value` changes `b.value` too.
Robert Rossney
You're right, corrected, thanks.
BrainCore
+2  A: 

You cannot type cast a baseclass instance to a subclass instance, so there's no way to for k to be of type B. What you can do is create an instance of B based on k, e.g.

k = A()
foo = B(k)

and you would copy all the interesting bits from k to foo in B's __init__() method, possibly everything with BrainCore's self.__dict__ = k.__dict__ method (just make sure you do a deep copy if necessary).

The question is why do you have to do this? Can't you just create an instance of B instead of an instance of A to begin with?

liwp
You are assuming that Python is some language like C++ or Java, in which changing an object's class is not possible. So you get convoluted workarounds, like Scott Meyers' "envelope-letter" idiom, so that an object *appears* to change type, but what really happens is that the content of the envelope changes to an object of a different type. What the OP is asking is in Python as simple as `k.__class__ = B`. It is possible that after having created k, with say method foo(), the OP has decided that the object should really apply some specialized version of foo() as defined in A's subclass B.
Paul McGuire
+2  A: 

This does the "class conversion" but it is subject to colateral 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
jsbueno