为了账号安全,请及时绑定邮箱和手机立即绑定
慕课网数字资源数据库体验端
Python编写有参数的decorator,Python3 进阶教程(新版)教程-慕课网
章节
课签
笔记
占位
占位

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('[{}] {}()...'.format(prefix, f.__name__))
            return f(*args, **kw)
        return wrapper
    return log_decorator

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

执行结果:

[DEBUG] test()...

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

# 标准decorator:
def log_decorator(f):
    def wrapper(*args, **kw):
        print('[{}] {}()...'.format(prefix, f.__name__))
        return f(*args, **kw)
    return wrapper
return log_decorator

# 返回decorator:
def log(prefix):
    return log_decorator(f)

任务

上一节的@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)

需要三层嵌套的decorator来实现。

参考答案:

import time
def performance(unit):
    def perf_decorator(f):
        def wrapper(*args, **kwargs):
            t1 = time.time()
            r = f(*args, **kwargs)
            t2 = time.time()
            t = (t2 - t1) * 1000 if unit == 'ms' else (t2 - t1)
            print('call {}() in {} {}'.format(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))
factorial(10)
||

写笔记

公开笔记
提交
||

请验证,完成请求

由于请求次数过多,请先验证,完成再次请求

收藏课程后,能更快找到我哦~

使用 Ctrl+D 可将课程添加到书签

举报

0/150
提交
取消