Python进阶(八)-编写带参数decorator

来源:互联网 发布:微软sql 编辑:程序博客网 时间:2024/05/18 03:08

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_decoratordef 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():    passprint 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 wrapperreturn log_decorator# 返回decorator:def log(prefix):    return log_decorator(f)

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

举例

  在@performance实现打印秒的同时,请给 @performace 增加一个参数,允许传入’s’或’ms’:

@performance('ms')def factorial(n):    return reduce(lambda x,y: x*y, range(1, n+1))

  要实现带参数的@performance,就需要实现:

my_func = performance('ms')(my_func)

需要3层嵌套的decorator来实现。
参考代码:

import timedef performance(unit):    def perf_decorator(f):        def wrapper(*args, **kw):            t1 = time.time()            r = f(*args, **kw)            t2 = time.time()            t = (t2 - t1) * 1000 if unit=='ms' else (t2 - t1)            print 'call %s() in %f %s' % (f.__name__, t, unit)            return r        return wrapper    return perf_decorator@performance('ms')def factorial(n):    return reduce(lambda x,y: x*y, range(1, n+1))print factorial(10)


这里写图片描述

2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 风寒感冒流清鼻涕怎么办 流清鼻涕吐黄痰不发烧怎么办 宝宝流黄鼻涕发烧怎么办 感冒了浓鼻涕多怎么办 感冒流浓鼻涕怎么办速效办法 孩子一直流清水鼻涕怎么办 宝宝鼻子呼噜呼噜响怎么办 鼻涕往嗓子里流怎么办 咳嗽痰多鼻涕多怎么办 没感冒嗓子痰多鼻涕怎么办 孩子感冒后鼻涕特别多怎么办 经常有鼻涕怎么办才好 怀孕后鼻涕痰多怎么办 鼻炎有鼻涕痰多怎么办 宝宝咳嗽痰多鼻涕多怎么办 宝宝两岁清鼻涕咳嗽痰多怎么办 喉咙咸咸的有痰怎么办 宝宝咳嗽鼻塞喉咙有痰怎么办 绝地求生刺激战场射击键误触怎么办 在皮卡堂卡的游泳了怎么办 假如遇到老赖没能力还钱怎么办 服刑人拒不执行伤害赔偿怎么办? 面对当前严峻形势作为军人怎么办 想起诉不知道对方地址怎么办 遇见家里来嫌疑人员怎么办 老滚5老婆死了怎么办 美化包安装之后闪退怎么办 蕉下的伞坏了怎么办 苹果7通话音质特别差怎么办 雨伞的伞骨坏了怎么办 雨伞的铁丝掉了怎么办 手机银行验证码忘了怎么办 应用安装验证码忘了怎么办 大王卡激活码找不到了怎么办 信用卡的激活码找不到怎么办 育碧账号忘了怎么办 uplay八折券丢了怎么办 不小心按到了育碧解绑怎么办 台式电脑连不上网怎么办 重装系统也安装不了cad怎么办 染发灰色偏绿了怎么办