Python: how to inherit and override
How you construct an object of subclass B
"based on" one of class A
depends exclusively on how the latter keeps state, if any, and how do you best get to that state and copy it over. In your example, instances of A
are stateless, therefore there is absolutely no work you need to do in B
's '__init__'
. In a more typical example, say:
class A(object):
def __init__(self):
self._x = 23
self._y = 45
def f(self):
print 'in f,', self._x
def h(self):
print 'in h,', self._y
the state would be in the two instance attributes _x
and _y
, so those are what you need to copy over:
class B(A):
def __init__(self, a):
self._x = a._x
self._y = a._y
def f(self):
print 'in B->f,', self._x
This is the most common and normal approach, where the subclass accepts and directly implements its state-dependence on the superclass -- it's very straightforward and linear.
You normally look for A
's instance state aspects in A
's '__init__'
, because most normal, straightforward Python code establishes instance state at initialization (attributes might be added and removed later, or even from code outside of the class's body, but that's not common and generally not advisable).
It is possible to add a little touch of "magic" (introspection-based programming), e.g...:
class B1(A):
def __init__(self, a):
try: s = a.__getstate__()
except AttributeError: s = a.__dict__
try: self.__setstate__(s)
except AttributeError: self.__dict__.update(s)
getstate is a special method that classes may define -- if they do, it's used (e.g. by pickling) to "get the state" of their instances for serialization purpose (otherwise, the instance's __dict__
is deemed to be the instance's "state"). It may return a dict (in which case the .update
call updates self
's state), but it may also return anything else if the class also defines a __setstate__
that accepts it (so this code tries that route first, before falling back to the update possibility). Note that in this use case either or both of the special methods would be inherited from A
-- I wouldn't define / override them in B
(unless there are further subtle goals to be achieved that way of course;-).
Is it worth using these four lines of "magic" in lieu of the simple assignments I first suggested? Mostly, no -- simplicity is preferable. But if A
does anything special or is subject to external code altering its state, this solution can be more powerful and general (that's what you're buying by accepting its complication). So, you have to know if the latter case applies (and then "go for the big guns" of the special state-related methods), or if A
and its instances are "pretty normal vanilla ones", in which case I would strongly recommend choosing simplicity and clarity instead.
Try this:
class A:
def f(self):
print("in f")
def h(self):
print("in h")
class B(A):
def f(self):
print("in B:f")
def test(x):
x.f()
x.h()
test(A())
test(B())
Note, I'm using Python 3, which is the reason for print
taking the arguments in parenthesis.
Output:
in f
in h
in B:f
in h
You need to put the self
argument into the argument list for instance methods in python.
Once you've done that, it will just work, because all methods are virtual in python.