zoukankan      html  css  js  c++  java
  • python中编写带参数decorator

    考察上一节的 @log 装饰器:

    def log(f):
        def fn(x):
            print 'call ' + f.__name__ + '()...'
            return f(x)
        return fn

    发现对于被装饰的函数,log打印的语句是不能变的(除了函数名)。

    如果有的函数非常重要,希望打印出'[INFO] call xxx()...',有的函数不太重要,希望打印出'[DEBUG] call xxx()...',这时,log函数本身就需要传入'INFO'或'DEBUG'这样的参数,类似这样:

    @log('DEBUG')
    def my_func():
        pass

    把上面的定义翻译成高阶函数的调用,就是:

    my_func = log('DEBUG')(my_func)

    上面的语句看上去还是比较绕,再展开一下:

    log_decorator = log('DEBUG')
    my_func = log_decorator(my_func)

    上面的语句又相当于:

    log_decorator = log('DEBUG')
    @log_decorator
    def my_func():
        pass

    所以,带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收my_func并返回新函数:

    def log(prefix):
        def log_decorator(f):
            def wrapper(*args, **kw):
                print '[%s] %s()...' % (prefix, f.__name__)
                return f(*args, **kw)
            return wrapper
        return log_decorator
    
    @log('DEBUG')
    def test():
        pass
    print test()

    执行结果:

    [DEBUG] test()...
    None

    对于这种3层嵌套的decorator定义,你可以先把它拆开:

    # 标准decorator:
    def log_decorator(f):
        def wrapper(*args, **kw):
            print '[%s] %s()...' % (prefix, f.__name__)
            return f(*args, **kw)
        return wrapper
    return log_decorator
    
    # 返回decorator:
    def log(prefix):
        return log_decorator(f)

    拆开以后会发现,调用会失败,因为在3层嵌套的decorator定义中,最内层的wrapper引用了最外层的参数prefix,所以,把一个闭包拆成普通的函数调用会比较困难。不支持闭包的编程语言要实现同样的功能就需要更多的代码。

  • 相关阅读:
    JVM基础和调优(一)
    Jtree(节点的渲染+资源管理器)(2)
    Jtree (节点的渲染+资源管理器)
    jtree(选择框)
    java进阶计划
    SQL优化
    spring 事务管理
    Spring事务配置的五种方式(转)
    spring与数据库之间的配置
    struct2(六) 为表单添加验证
  • 原文地址:https://www.cnblogs.com/Lambda721/p/6128990.html
Copyright © 2011-2022 走看看