I'm writing a metaclass, and I want an additional method to be called between __new__ and __init__.
If I were calling the method before __new__ or after __init__ I could write e.g.
class Meta(type):
def __call__(cls):
ret = type.__call__()
ret.extraMethod()
My temptation is to write
class Meta(type):
def __call__(cls):
ret = cls.__new__(cls)
ret.extraMethod()
ret.__init__()
return ret
and just reproduce the functionality of type.__call__ myself. But I'm afraid there might be some subtlety to type.__call__ I have omitted, which will lead to unexpected behavior when my metaclass is implemented.
I cannot call extraMethod from __init__ or __new__ because I want users of my metaclass to be able to override __init__ and __new__ as in normal Python classes, but to still execute important set-up code in extraMethod.
Thanks!
If you really wish to do exactly what you said I can suggest you the following solution:
def call_after(callback, is_method=False):
def _decorator(func):
def _func(*args, **kwargs):
result = func(*args, **kwargs)
callback_args = (result, ) if is_method else ()
callback(*callback_args)
return result
return _func
return _decorator
class Meta(type):
def __new__(mcs, class_name, mro, attributes):
new_class = super().__new__(mcs, class_name, mro, attributes)
new_class.__new__ = call_after(
new_class.custom_method,
is_method=True
)(new_class.__new__)
return new_class
class Example(object, metaclass=Meta):
def __new__(cls, *args, **kwargs):
print('new')
return super().__new__(cls, *args, **kwargs)
def __init__(self):
print('init')
def custom_method(self):
print('custom_method')
if __name__ == '__main__':
Example()
This code will generate the following result:
new
custom_method
init
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With