(How) Is it possible in Python to treat an instance of class B exactly as an instance of class A, where A is a parent of B (like up-casting in compiled languages)?
Say we have the following:
class A:
def __init__(self, prop=None):
self.prop = prop
def f(self):
return 'A.f'
def g(self):
return 'A.g', self.f()
class B(A):
def f(self):
return 'B.f'
def g(self):
return 'B.g', self.f()
Calling A().g() produces ('A.g', 'A.f'), whereas B().g() produces ('B.g', 'B.f'). Calling super(B, B()).g() produces ('A.g', 'B.f'), which is different from compiled languages, so I cannot use super. Instead, I need a function that changes the type from which an instance's methods are resolved, but preserves (a reference to) the original state. In short, I'm looking for a way to do this:
b = B(object())
a = upcast(b, A)
a.prop = object()
assert isinstance(a, A)
assert a.g() == ('A.g', 'A.f')
assert a.prop is b.prop
The closest I could get is
a = copy.copy(b)
a.__class__ = A
a.__dict__ = b.__dict__
(assuming A/B are "nice" "heap" classes), but this makes unnecessary copies of all objects in the __dict__ before I discard them. Is there a better way to do this?