import decorator

decorator 是一个帮助你更优雅的编写 decorator 的 decorator


以最常用的 memoize decorator 为例:

原生的写法如下

def memoize(func):
    def _memoize(*args, **kw):
        if not hasattr(func, 'cache'):
            func.cache = {}
        if kw:  # frozenset is used to ensure hashability
            key = args, frozenset(kw.items())
        else:
            key = args
        if key not in func.cache:
            func.cache[key] = func(*args, **kw)
        return func.cache[key]
    return functools.update_wrapper(_memoize, func)

decorator 版如下:

import decorator

@decorator.decorator
def memoize(func, *args, **kw):
    if not hasattr(func, 'cache'):
        func.cache = {}
    if kw:  # frozenset is used to ensure hashability
        key = args, frozenset(kw.items())
    else:
        key = args
    cache = func.cache  # attribute added by memoize
    if key not in cache:
        cache[key] = func(*args, **kw)
    return cache[key]

更复杂的,带参 decorator(or decorator factory)

原生的写法如下

def memoize(print_cache):
    def _memoize(func):
        def __memoize(*args, **kw):
            if not hasattr(func, 'cache'):
                func.cache = {}
            if kw:  # frozenset is used to ensure hashability
                key = args, frozenset(kw.items())
            else:
                key = args
            if key not in func.cache:
                func.cache[key] = func(*args, **kw)
            if print_cache:
                print(func.cache)
            return func.cache[key]
        return functools.update_wrapper(__memoize, func)
    return _memoize

decorator 版如下:

@decorator.decorator
def memoize(func, print_cache=False, *args, **kw):
    if not hasattr(func, 'cache'):
        func.cache = {}
    if kw:  # frozenset is used to ensure hashability
        key = args, frozenset(kw.items())
    else:
        key = args
    cache = func.cache  # attribute added by memoize
    if key not in cache:
        cache[key] = func(*args, **kw)
    if print_cache:
        print(func.cache)
    return cache[key]

总的来说,decorator 允许你只用一个单层的函数定义来编写一个 decorator,而不是像原生的写法那个样需要写成嵌套的形式,让你的精力集中在 decorator 的内容上而不是形式上
此外,即使使用了functools.update_wrapper,被装饰的函数只会保留__name__, __doc__, __module__, __dict__,但是会丢失原始函数的 __code__等,decorator 帮你解决了这个问题

比如

>>> @memoize
>>> def fun(x):
>>>     return x

原生写法

>>> print(fun.__code__.co_varnames)
>>> ('args', 'kw', 'key')

decorator 版写法

>>> print(fun.__code__.co_varnames)
>>> ('x', )
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Python进阶框架 希望大家喜欢,点赞哦首先感谢廖雪峰老师对于该课程的讲解 一、函数式编程 1.1 函数式编程简...
    Gaolex阅读 5,524评论 6 53
  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 1,563评论 0 6
  • 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。 函数对象有一个__name__...
    劉光軍_MVP阅读 134评论 0 0
  • 认识阿渡和小乔,是因为参加鼎泰风华微微童书吧筹备会。 那是我们第一次见面,此前对阿渡的了解,是因为嘉诺赏对阿渡的采...
    藕礼君_莲藕阅读 445评论 0 0
  • 没有一蹴而就的成功,只有一步一脚印地走向成功。你只看到别人的成就,却没有看见别人的努力,甚至拼尽全力。那些大咖...
    迎风裙子阅读 379评论 7 7