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