• 理解Python的装饰器


    看Flask文档时候看到关于cache的装饰器,有这么一段代码:

    def cached(timeout=5 * 60, key=’view/%s’):
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                cache_key = key % request.path
                rv = cache.get(cache_key)
                if rv is not None:
                    return rv
                rv = f(*args, **kwargs)
                cache.set(cache_key, rv, timeout=timeout)
                return rv
            return decorated_function
        return decorator

    之前也略懂装饰器,但是仔细一看发现了区别。

    一般的装饰器代码是这样的:

    def login_required(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if g.user is None:
                return redirect(url_for(’login’, next=request.url))
            return f(*args, **kwargs)
        return decorated_function

    看出区别了吗?

    第一个里面有两层def,第二个只有一层!

    我的好奇心一下就上来了,非要把这个东西搞明白不可。

    研究了一会总算研究明白了,下面就开始讲解吧。

    首先理解一般的装饰器到底是怎么工作的:

    def login_required(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if g.user is None:
                return redirect(url_for(’login’, next=request.url))
            return f(*args, **kwargs)
        return decorated_function
    
    
    @login_required
    def test():
        print "haha"

    我们用login_required装饰了test函数,那么实际上执行的语句可以理解成这样:

    test = login_required(test)

    也就是说,现在test变成了login_required(test)的执行结果,也就是变成了decorated_function函数。

    所以我们每次执行test的时候,其实执行的就是decorated_function,而原来的test函数就变成了decorated_function中的f函数。实现了装饰功能。

    下面我们看看两层嵌套的装饰器到底是怎么工作的:

    def cached(timeout=5 * 60, key=’view/%s’):
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                cache_key = key % request.path
                rv = cache.get(cache_key)
                if rv is not None:
                    return rv
                rv = f(*args, **kwargs)
                cache.set(cache_key, rv, timeout=timeout)
                return rv
            return decorated_function
        return decorator
    
    
    @cached(100)
    def test():
        pass

    好像没什么区别?

    再仔细看看!

    @cached(100)

    这里多了个参数!

    是的,秘密就在这个参数。

    加了参数之后,装饰器的装饰过程变成了两步:

    cached_temp = cached(100)
    test = cached_temp(test)

    Python内部肯定没有cached_temp这个变量,这是我加的。不过实际的执行过程就是这么个顺序,这下就一目了然了吧!

    首先运行cached(100),这时候返回的是第一层def,也就是真正的装饰器。

    然后运行cached_temp(test),这时候返回了第二层def,这步就和一般的装饰器一样了。

    我们总结一下,嵌套两层def的目的就是实现“带参装饰器”,相当于可以通过参数来定制一个装饰器,然后再应用到函数上。

    明白了吗?

  • 相关阅读:
    Linux 下 MQ 的安装
    云计算的三种服务模式:IaaS,PaaS和SaaS
    Mac下安装Maven
    JDK Mac 安装
    Mac OS 终端利器 iTerm2
    单元测试用例规范
    boolean 属性的定义规范
    2019-12-9号 终于入职 阿里巴巴
    远程调试方法
    系统提测及上线规范(系统上线必读!)
  • 原文地址:https://www.cnblogs.com/numbbbbb/p/3616017.html
Copyright © 2020-2023  润新知