Converting An Object Into A Subclass In Python?
Solution 1:
This can be done if the initializer of the subclass can handle it, or you write an explicit upgrader. Here is an example:
classA(object):def__init__(self):
self.x = 1classB(A):def__init__(self):
super(B, self).__init__()
self._init_B()
def_init_B(self):
self.x += 1
a = A()
b = a
b.__class__ = B
b._init_B()
assert b.x == 2
Solution 2:
Since the library function returns an A, you can't make it return a B without changing it.
One thing you can do is write a function to take the fields of the A instance and copy them over into a new B instance:
classA: # defined by the librarydef__init__(self, field):
self.field = field
classB(A): # your fancy new classdef__init__(self, field, field2):
self.field = field
self.field2 = field2 # B has some fancy extra stuffdefb_from_a(a_instance, field2):
"""Given an instance of A, return a new instance of B."""return B(a_instance.field, field2)
a = A("spam") # this could be your A instance from the library
b = b_from_a(a, "ham") # make a new B which has the data from aprint b.field, b.field2 # prints "spam ham"
Edit: depending on your situation, composition instead of inheritance could be a good bet; that is your B class could just contain an instance of A instead of inheriting:
classB2: # doesn't have to inherit from Adef__init__(self, a, field2):
self._a = a # using composition insteadself.field2 = field2
@propertydeffield(self): # pass accesses to areturnself._a.field
# could provide setter, deleter, etc
a = A("spam")
b = B2(a, "ham")
print b.field, b.field2 # prints "spam ham"
Solution 3:
you can actually change the .__class__
attribute of the object if you know what you're doing:
In [1]: classA(object):
...: deffoo(self):
...: return"foo"
...:
In [2]: classB(object):
...: deffoo(self):
...: return"bar"
...:
In [3]: a = A()
In [4]: a.foo()
Out[4]: 'foo'
In [5]: a.__class__
Out[5]: __main__.A
In [6]: a.__class__ = B
In [7]: a.foo()
Out[7]: 'bar'
Solution 4:
Monkeypatch the library?
For example,
import other_library
other_library.function_or_class_to_replace = new_function
Poof, it returns whatever you want it to return.
Monkeypatch A.new to return an instance of B?
After you call obj = A(), change the result so obj.class = B?
Post a Comment for "Converting An Object Into A Subclass In Python?"