装饰器

"""
decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。
编写有无参数的decorator
"""
import time
from functools import reduce


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


@log
def factorial(n):
    return reduce(lambda x, y: x + y, range(1, n+1))

# print(factorial(10))


@log
# 对于参数不是一个的函数,调用将报错:
def add(x, y):
    return x + y

# print(add(2, 3))    # TypeError: fn() takes 1 positional argument but 2 were given


"""
因为 add() 函数需要传入两个参数,但是 @log 写死了只含一个参数的返回函数。
要让 @log 自适应任何参数定义的函数,可以利用Python的 args 和 *kwargs,保证任意个数的参数总是能正常调用
"""


# 重写log函数为 logs函数
def logs(f):
    def fn(*args, **kwargs):
        print('call ' + f.__name__ + '()...')
        return f(*args, **kwargs)
    return fn


@logs
def add(x, y):
    return x + y

# print(add(2, 3))



# 请编写一个@performance,它可以打印出函数调用的时间
def performance(f):
    def fn(*args, **kwargs):
        start_time = time.time()
        # print(start_time)
        r = f(*args, **kwargs)
        end_time = time.time()
        # print(end_time)
        print(f'call time:{end_time - start_time}')
        return r
    return fn


@performance
def factory(n):
    time.sleep(1)
    return reduce(lambda x, y: x + y, range(1, n+1))


# print(factory(10))



"""
编写有参数的decorator:
上述的代码,发现对于被装饰的函数,log打印的语句是不能变的(除了函数名)。

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

 

posted @ 2023-03-13 00:06  雪儿来  阅读(20)  评论(0编辑  收藏  举报