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)

 

posted @ 2018-04-18 14:21  亚洲哈登  阅读(200)  评论(0编辑  收藏  举报