python 装饰器
需求:
一个加法函数,想增强它的功能,能够输出加法函数的日志信息
def add(x, y): return x + y
增加信息输出功能:
def add(x, y): print("call add,x + y") #日志输出到控制台 return x + y
上面的加法函数是完成了需求,但是有以下的缺点:
打印日志信息是一个功能,这条语句和 add 函数耦合太高;
加法函数属于业务功能,而输出日志信息的功能,属于非业务功能代码,不该放在业务函数 add 中;
下面代码做到了业务功能分离,但是 fn 函数调用传参是个问题:
def add(x, y): return x + y def logger(fn): print(‘before‘) print(‘add function:{} {}‘.format(4, 5)) ret = fn(4, 5) print(‘after‘) return ret print(logger(add))
解决了传参的问题,进一步改变:
def add(x, y): return x + y def logger(fn, *args, **kwargs): print(‘before‘) print(‘add function:{} | {}‘.format(args, kwargs)) ret = fn(*args, **kwargs) # 参数解构 print(‘after‘) return ret print(logger(add, 4, 5)) print(logger(add, x=4, y=6)) print(logger(add, 4, y=15))
柯里化:
def add(x, y): return x + y def logger(fn): def wrapper(*args, **kwargs): print(‘before‘) print(‘add function:{} | {}‘.format(args, kwargs)) ret = fn(*args, **kwargs) # 参数解构 print(‘after‘) return ret return wrapper print(logger(add)(4, 5)) # 换一种写法: ‘‘‘ add = logger(add) print(add(x=5, y=10)) ‘‘‘ # 1.先算等式右边,logger(add) # 2.add函数对象被fn记住 # 3.logger函数返回 wrapper,即add = wrapper # 4.调用add(4, 5)即wrapper(4, 5) # 5.ret = fn(*args, **kwargs),此处的fn记住的是最原始的add函数对象
装饰器语法糖:
def logger(fn): def wrapper(*args, **kwargs): print(‘before‘) print(‘add function:{} | {}‘.format(args, kwargs)) ret = fn(*args, **kwargs) # 参数解构 print(‘after‘) return ret return wrapper @logger # 等价于add = logger(add) def add(x, y): return x + y print(add(20, 30)) ‘‘‘ 可以采用逆推思维: 1.add(20, 30) 2.包装add(20, 30)为:wrapper(20, 30) 3.实现日志增强功能:logger(add)(20, 30) 即:add(20, 30) => wrapper(20, 30) => logger(add)(20, 30) def logger(fn): def wrapper(*args, **kwargs): val = fn(*args, **kwargs) return val return wrapper @logger def add(x, y): return x + y ‘‘‘
@logger是什么?这就是装饰器语法
装饰器(无参)
它是一个函数
函数作为它的形参,无参装饰器实际上就是一个单形参函数
返回值也是一个函数 可以使用 @functionname 方式,简化调用
注:此处装饰器的定义只是就目前所学的总结,并不准确,只是方便理解
装饰器和高阶函数
装饰器可以是高阶函数,但装饰器是对传入函数的功能的装饰(功能增强)
相关推荐
FlySky 2020-10-16
FlySky 2020-09-29
bizercsdn 2020-09-17
python0 2020-08-16
chenzulong 2020-08-16
LULUBAO 2020-07-08
一叶不知秋 2020-06-28
yogoma 2020-06-14
周小董 2020-06-10
hongxiangping 2020-06-09
xmwang0 2020-06-08
JJandYY 2020-05-31
Andrewjdw 2020-05-27
wklken的笔记 2020-05-27
zhuquan0 2020-05-26
chongtianfeiyu 2020-05-20
qianjq 2020-05-10
小方哥哥 2020-05-05