zoukankan      html  css  js  c++  java
  • 理解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的目的就是实现“带参装饰器”,相当于可以通过参数来定制一个装饰器,然后再应用到函数上。

    明白了吗?

  • 相关阅读:
    shell学习小结
    数据结构基础
    IComparable接口实现自定义类型的排序
    RavenDb进行全文检索实现及数据统计
    移动开发经验总结(monotouch&monodroid)
    Maven pom.xml中的元素modules、parent、properties以及import
    StaticHtml1.0beta
    asp.net 页面静态化
    JQuery常用方法
    ASP.NET无刷新多文件文件上传系统(转载)
  • 原文地址:https://www.cnblogs.com/numbbbbb/p/3616017.html
Copyright © 2011-2022 走看看