I want to wrap a function name funky_the_function
with an object which has a __call__
method defined.
Without using functools.wraps
the name of the wrapped function will be lost and so will the docstring.
How do I create a meta-class such that instances of the class are wrapped in functools.wraps
?
import functools
class MetaDecorator(type):
def __call__(self, *args):
super().__call__(*args)
# SOMEWHERE INSIDE OF `__call__` WE HAVE:
# obj = functools.wraps(obj)
class Decorator(metaclass=MetaDecorator):
def __init__(f):
assert(callable(f))
self._f = f
def __call__(self, *args, **kwargs):
return self._f(*args, **kwargs)
@Decorator
def funky_the_function(*args, **kwargs):
"""Documentation string"""
print('Called example function')
print(funky_the_function.__name__)
print(funky_the_function.__doc__)
If you're looking for a way to fix the name and docstring, it can be easily fix by dynamically adding the __name__
and __doc__
to the instance. There is no need for meta-classes.
class Decorator:
def __init__(self, f):
assert callable(f)
self.__name__ = f.__name__
self.__doc__ = f.__doc__
self._f = f
def __call__(self, *args, **kwargs):
return self._f(*args, **kwargs)
Of course you can do this in metaclass as well:
class MetaDecorator(type):
def __call__(self, f):
assert callable(f)
instance = super().__call__(f)
instance.__name__ = f.__name__
instance.__doc__ = f.__doc__
return instance
class Decorator(metaclass=MetaDecorator):
def __init__(self, f):
self._f = f
def __call__(self, *args, **kwargs):
return self._f(*args, **kwargs)
from functools import wraps
class MetaDecorator(type):
def __call__(self, f):
assert callable(f)
instance = super().__call__(f)
instance = wraps(f)(instance)
return instance
class Decorator(metaclass=MetaDecorator):
def __init__(self, f):
self._f = f
def __call__(self, *args, **kwargs):
return self._f(*args, **kwargs)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.