The Right Way
The correct way to do this would be to call the parent initializer in your code directly. In Python 3:
super().__init__()
In Python 2:
super(Parent, self).__init__()
or
super(Child, self).__init__()
The Error
To answer your immediate question though, the infinite recursion happens because of how you get the parent:
self.__class__.__bases__[0]
self
will not stop being an instance of Child
no matter how many times you call your wrapper
function. You end up calling Parent.__init__(self)
indefinitely because the parent class never changes.
The Wrong Way
What you probably want is to find the class that defined the __init__
method you are currently calling, and get the parent of that. @AlexMartelli has provided a function that does this or Python to in his answer, which I am copying verbatim here:
import inspect
def get_class_that_defined_method(meth):
for cls in inspect.getmro(meth.im_class):
if meth.__name__ in cls.__dict__:
return cls
return None
I you are using Python 3, use @Yoel's version instead:
def get_class_that_defined_method(meth):
if inspect.ismethod(meth):
for cls in inspect.getmro(meth.__self__.__class__):
if cls.__dict__.get(meth.__name__) is meth:
return cls
meth = meth.__func__ # fallback to __qualname__ parsing
if inspect.isfunction(meth):
cls = getattr(inspect.getmodule(meth),
meth.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0])
if isinstance(cls, type):
return cls
return getattr(meth, '__objclass__', None) # handle special descriptor objects
You can now redefine your init
function as follows:
def init(__init):
def wrapper(self, *args, **kwargs):
get_class_that_defined_method(__init).__bases__[0].__init__(self)
__init(self)
return wrapper
Again. Please do not do this. There are probably many corner cases that I have not covered that will come and bite you, starting with everything around __bases__[0]
. Just use super
instead. It is a much better thought out version of the same idea anyway.