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,所以,把一个闭包拆成普通的函数调用会比较困难。不支持闭包的编程语言要实现同样的功能就需要更多的代码。

时间: 2024-10-02 11:02:28

python中编写带参数decorator的相关文章

编写带参数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(

[译]SSRS 编写带参数的MDX报表

编写MDX报表长久以来对于报表人员来说都比较痛苦. 当然如果你用查询设计器(Query Designer) 直接拖拉数据集那就很方便,但是你们有没有想过查询设计器是怎么创建MDX的.或者创建的参数是如何工作的? 我听到很多用Analysis Services 作为数据源的(包括我)报表人员说写参数太难了,所以他们用查询设计器做报表. 我想关键的问题是查询设计器做的MDX看起来要比实际上更复杂.如果你知道一些MDX基础,你应该能直接写MDX而不是用查询分析器 ,你就是喜欢用查询分析器也没关系.本文

python 中函数的参数

一.python中的函数参数形式 python中函数一般有四种表现形式: 1.def function(arg1, arg2, arg3...) 这种是python中最常见的一中函数参数定义形式,函数参数之间用逗号分隔,调用的时候的参数必须与定义的时候相同,且参数顺序与形参一一对应. ? 1 2 3 4 5 6 7 8 9 def myfunction(a, b):     print a,b #正确调用 myfunction(3,7) #错误调用 myfunction(3) myfunctio

python中的可变参数

def foo(*args, **kwargs): print 'args = ', args print 'kwargs = ', kwargs print '---------------------------------------' if __name__ == '__main__': foo(1,2,3,4) foo(a=1,b=2,c=3) foo(1,2,3,4, a=1,b=2,c=3) foo('a', 1, None, a=1, b='2', c=3) 输出结果如下:arg

python中的魔法参数:*args和**kwargs

def foo(*args, **kwargs):print 'args = ', argsprint 'kwargs = ', kwargsprint '---------------------------------------'if __name__ == '__main__':foo(1,2,3,4)foo(a=1,b=2,c=3)foo(1,2,3,4, a=1,b=2,c=3)foo('a', 1, None, a=1, b='2', c=3) 输出结果如下:args = (1,

Object-C中编写省略参数的多参函数

Object-C中编写省略参数的多参数函数 引语: 在Object-C中,我们会遇到很多像NSLog这样的函数,其中参数的个数不确定,由程序员自由控制,在初始化数组,字典等方面应用广泛,那么,这类的函数是如何实现的呢?我们怎么编写我们自己的省略参数的函数呢?当然,这不是唯一的多参函数的处理方法,你也可以通过一个字典或者数组传递参数.但C为我们提供的这样的一种机制,无疑是最方便的. 一.了解几个概念 va_list C语言中定义的一个指针,用于指向当前的参数. va_start(ap,param)

Python中的可变参数和关键字参数

刚开始接触 python 的时候,对 python 中的 *wargs (可变参数) 和 **kwargs (关键字参数)的理解不是很透彻,看了一下 <Explore Python>一书,里面对这一部分的描述相对浅显易懂, 这里依据个人理解进行相关总结. 可变参数(*args) 对于可变参数可以联想到 C# 中的可变参数.可变参数是一个数量不确定的列表集合,可以是 list 类型,也可以是 tuple 类型 我们定义如下代码段: def add(*numbers): print(type(nu

【转】如何在命令行脚本中启动带参数的Windows服务

我们有一个自己编写的Windows服务,我们希望该服务在启动时可以根据用户输入的参数实现不同的功能. 要实现这样的需求并不是很难,下面这个例子我用来示范如何编写该服务 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Diagnostics; 6 using System.Linq; 7 using Syste

Python中函数的参数定义和可变参数

转自:http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944416.html  简洁易懂啊,好文 刚学用Python的时候,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和**让人有点费解.其实只要把函数参数定义搞清楚了,就不难理解了. 先说说函数定义,我们都知道,下面的代码定义了一个函数funcA def funcA():  pass    显然,函数funcA没有参数(同时啥也不干:D