I would like to create a class so that code is executed both before and after the __init__
of subclasses (defined by users of my class). I don't want to mandate to those users that they have to explicitly call superclass methods; it should happen automatically.
Here is the solution I have come up with, using __init_subclass__
:
# my class
class C:
def __init_subclass__(cls):
cls.__old_init__ = cls.__init__
cls.__init__ = cls.__init_wrapper__
cls.__init__.__doc__ = cls.__old_init__.__doc__
def __init_wrapper__(self, *args, **kwargs):
print('before __init__')
self.__old_init__(*args, **kwargs)
print('after __init__')
# user's class
class D (C):
def __init__(self, x):
"init D object"
This seems to work.
What I don't like about this solution is that when I call help(D)
, all my awkward machinery is exposed:
Help on class D in module __main__:
class D(C)
| D(*args, **kwargs)
|
| Method resolution order:
| D
| C
| builtins.object
|
| Methods defined here:
|
| __init__ = __init_wrapper__(self, *args, **kwargs)
|
| __old_init__ = __init__(self, x)
| init D object
|
| ----------------------------------------------------------------------
| Methods inherited from C:
|
| __init_wrapper__(self, *args, **kwargs)
| init D object
|
| ----------------------------------------------------------------------
| Class methods inherited from C:
|
| __init_subclass__() from builtins.type
| This method is called when a class is subclassed.
|
| The default implementation does nothing. It may be
| overridden to extend subclasses.
|
| ----------------------------------------------------------------------
| Data descriptors inherited from C:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
Moreover, the copied docstring shows up on __init_wrapper__
(and of course __old_init__
) but not on the patched __init__
, and the call signature of __init__ = __init_wrapper__
is uninformative.
Is there a better way?