Python之装饰器
0.1高阶函数
def sort(iterable,reverse=False,key=lambda x,y:x<y): lst = [] for x in iterable: for k,v in enumerate(lst): if reverse: flag=key(x,v) else: flag= not key(x,v) if flag: lst.insert(k,x) break else: lst.append(x) return lst sort([2,5,6,1,4],reverse=True,key = lambda x,y:x>y)
1.1currying
指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第 二个参数为参数的函数
def add(x,y): return x+y
print(add(4,5)) 转换成 def add(x): def _add(y): return x+y return _add print(add(5)(6))
1.2装饰器的演变
#业务功能分离,fn函数调用传参是个问题 def add(x,y): return x+y def logger(fn): print('begin') x = fn(4,5) print('end') return x print(logger(add))
解决了传参问题,进一步修改函数
def add(x,y): return x+y def logger(fn,*args,**kwargs): print('begin') x = fn(*args,**kwargs) print('end') return x print(logger(add,5,5))
currying,改变函数调用的方式
#currying def add(x,y): return x+y def logger(fn): def _logger(*args,**kwargs): #*args传参组成元祖,**kwargs传参组成字典 print('begin') x = fn(*args,**kwargs) #*args,**kwargs是参数解构,此处fn调用了外层函数的参数fn是闭包 ;;add print('end') return x return _logger f = logger(add) #logger(add) 函数add已经传递进来给fn使用,左边重新赋值覆盖了add函数,引用计数后gc不垃圾回收 print(f(5,6))
f = logger(add)(5,6) #currying的调用方式,;logger(add)外层函数return 内层函数wrapper print(f)
add = logger(add) add(5,4) #这个add调用的已经不是add函数了 而是增强版的add带装饰器的add
logger(add)(4,5) #等价于 add = logger(add) -->add(4,5)
装饰器语法糖
def logger(fn): def wrapper(*args,**kwargs): x = fn (*args,**kwargs) return x return wrapper @logger #等价于 add = logger(add) def add(x,y): #由于add = logger(add)-->这里的add已经不是函数定义了 而是logger返回的return wrapper return x+y #return x+y 把返回值,传递给fn并且赋值给x,装饰器return x
1.3装饰器的副作用,以及带参数的装饰器
def copy_properties(src,dst): dst.__name__ = src.__name__ dst.__doc__ = src.__doc__ def logger(fn): def wrapper(*args,**kwargs): """I am wrapper""" x = fn(*args,**kwargs) return x copy_properties(fn,wrapper) return wrapper @logger def add(x,y): """This is function for add """ return x+y print("name={},doc={}".format(add.__name__,add.__doc__)) #备注参数wrapper.__name__=fn.__name__ ;fn的name属性是正常的 传递给wrapper的name属性 更改后 def copy_properties(src): def _copy_properties(dst): dst.__name__ = src.__name__ dst.__doc__ = src.__doc__ return dst return _copy_properties def logger(fn): @copy_properties(fn) #wrapper = copy_properties(fn)(wrapper) def wrapper(*args,**kwargs): """I am wrapper""" x = fn(*args,**kwargs) return x return wrapper @logger def add(x,y): """This is function for add """ return x+y print("name={},doc={}".format(add.__name__,add.__doc__))
带参数的装饰器
#带参数的装饰器 import datetime def logger(duration): def _logger(fn): def wrapper(*args,**kwargs): #被装饰函数需要传递参数的时候,需要装饰器里面添加*args,*kwargs;没有warpper也是带参数的装饰器 start = datetime.datetime.now() print('begin') x = fn(*args,**kwargs) end = datetime.datetime.now() print('too fast') if (end-start).total_seconds()<duration else print('too slow') print('end') return x return wrapper return _logger @logger(5) def add(x,y): time.sleep(2) return x+y add(5,6)
本文为原创文章,转载请标明出处