"""
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'这样的参数
"""