装饰器
装饰器是AOP面向切面编程Aspect Oriented Programming的思想的体现.
它是一种不改变原来的业务代码,给程序动态添加功能的技术.
无参装饰器
□ 无参装饰器
□ 首先,装饰器是一个高阶函数
□ 装饰器要有一个函数作为参数
□ 装饰器的返回值也是一个函数
□ 可以使用@functionname方式简化调用
□ 它是对传入的函数的功能增强,对原有函数不做改变
假设现在我们有一个简单的需求,在add(x, y)函数调用前后分别打印一句话,并且不能对add函数本身进行变动.
传统写法
def add(x, y):
return x + y
def logger(fn, *args, **kwargs):
print("before ....")
ret = fn(*args, **kwargs)
print(ret)
print("after ....")
#调用:
logger(add, 1, 5)
#还可以进一步柯里化
def logger(fn):
def wrapper(*args, **kwargs):
print("before ....")
ret = fn(*args, **kwargs)
print(ret)
print("after ....")
return ret
return wrapper
#调用:
logger(add)(1, 5)
# 解析:
# logger(add)返回值为wrapper,它是一个函数
# 而wrapper(1, 5)即为调用
上面的调用可以写成:
add = logger(add)
add(1, 5)
# 这里第一步add = logger(add) 可能比较容易产生歧义
#
# 下面我们从最开始定义add函数时开始进行分析
# add是一个标识符,它引用了一个函数fnc(fnc内存引用计数+1), 而logger(add),这里由于logger函数内的
# wrapper函数也用到了fnc,所以它的内存引用计数+1(假设此时为2),然后再来看add = logger(add)
# 这一行,等号左边,由重新定义了add这个标识符,此时,它对原函数不再引用,
# 因此原函数的引用计数-1(即2-1=1),但此时fnc依然有被引用,所以此函数还是存在的.
# 而logger的返回值是wrapper函数,这时add被赋值为wrapper的引用,而不再是fnc的引用,
# 此时wrapper的内存引用计数+1
# 那么此时的add已经不是最开始的add了,它其实是对wrapper的引用
装饰器写法
接下来我们就引出了装饰器语法
def logger(fn):
def wrapper(*args