Python functools.wraps equivalent for classes

前端 未结 5 1691
予麋鹿
予麋鹿 2020-12-04 09:13

When defining a decorator using a class, how do I automatically transfer over__name__, __module__ and __doc__? Normally, I would use

5条回答
  •  甜味超标
    2020-12-04 09:43

    Another solution using inheritance:

    import functools
    import types
    
    class CallableClassDecorator:
        """Base class that extracts attributes and assigns them to self.
    
        By default the extracted attributes are:
             ['__doc__', '__name__', '__module__'].
        """
    
        def __init__(self, wrapped, assigned=functools.WRAPPER_ASSIGNMENTS):
            for attr in assigned:
                setattr(self, attr, getattr(wrapped, attr))
            super().__init__()
    
        def __get__(self, obj, objtype):
            return types.MethodType(self.__call__, obj)
    

    And, usage:

    class memoized(CallableClassDecorator):
        """Decorator that caches a function's return value each time it is called.
        If called later with the same arguments, the cached value is returned, and
        not re-evaluated.
        """
        def __init__(self, function):
            super().__init__(function)
            self.function = function
            self.cache = {}
    
        def __call__(self, *args):
            try:
                return self.cache[args]
            except KeyError:
                value = self.function(*args)
                self.cache[args] = value
                return value
            except TypeError:
                # uncacheable -- for instance, passing a list as an argument.
                # Better to not cache than to blow up entirely.
                return self.function(*args)
    

提交回复
热议问题