通过我们的python柯里化就能学习装饰器啦~!

装饰器应该是目前来说学到的比较困难的,非常非常重要,下面根据代码演化出装饰器


需求:

  一个加法函数,想增强它的功能,能够输出被调用过以及调用的参数信息

def add(x, y, file):    print("call {}, {} + {}".format(add.__name__, x, y), file=file)    """"    __name__是一个特殊的属性,将日志输出到控制台    print函数后面其实还可以跟file,将输出信息输出到其它地方,比如d:/123    """    return x + yprint(add(4, 5))

上面的加法函数是完成了需求,但是有以下的缺点:

  打印语句的耦合太高;

  加法函数属于业务功能,而输出信息的功能,属于非业务功能代码,不该放在业务函数加法中;

  这种写法有种称呼叫做侵入式代码;

想一下想要对函数的功能进行增强怎么办呢?如何做到业务功能离?

def add(x, y):    return x + ydef logger(function):    print('-------begin-----')# 增强的输出    x = function(4, 5)# 相当于x = add(4, 5)    print('------end--------')# 增强的功能    return xprint(logger(add))

上面代码做到了业务功能分离,但是x = function(4, 5)这里会有问题,这里被写死了?该如何做呢?

def add(x, y):    return x + ydef logger(function, x, y):    print('-------begin-----')    x = function(x, y)    print('------end--------')    return xprint(logger(add))

这样能做到,但是还是有问题,如果我的函数是这样写的,怎么办?

def add1(x, y):    return x + ydef add2(x, y, z):    return x + y + zdef logger(function, x, y):# x, y这里写死肯定不行啦    print('-------begin-----')    x = function(x, y)    print('------end--------')    return xprint(logger(add1))print(logger(add2)) ####

怎么搞定呢?

def add1(x, y):    return x + ydef add2(x, y, z):    return x + y + zdef add3(x, y, *args, z):    return x + y + zdef logger(function, *args, **kwargs):    print('-------begin-----')    x = function(*args, **kwargs)    print('------end--------')    return xprint(logger(add1, 4, 5))print(logger(add2, 4, 5, 6))print(logger(add3, 4, z=5, y=6))

试想还能不能在变化一下?(柯里化)

def add1(x, y):    return x + ydef add2(x, y, z):    return x + y + zdef add3(x, y, *args, z):    return x + y + zdef logger(function):    def _logger(*args, **kwargs):        print('-------begin-----')        x = function(*args, **kwargs)        print('------end--------')        return x    return _loggerfoo = logger(add1)print(foo(10, 20))

如果把foo = logger(add1)换成add1 = logger(add1),这样会不会报错?

不会报错,那么就有更简单的方式了———装饰器

def logger(function):    def _logger(*args, **kwargs):        print('-------begin-----')        x = function(*args, **kwargs)        print('------end--------')        return x    return _logger@logger # 这句相当于 add1 = logger(add1)def add1(x, y):    return x + yprint(add1(4, 5))

这就是装饰器函数.

@logger这句是语法糖,相当于add1 = logger(add1),所以当最后一句print(add1(4,5)),这里调用的add1相当于调用的是logger函数

的内层函数,跟def add1(x, y)这句没有关系了

这就是装饰器的演化,但是前面几个技术需要熟悉掌握,比如传参,解构的技巧

注意规范:

  外层函数要返回内层函数的引用;

  外层函数至少传入一个参数,这个参数应该是要被包装的一个函数;

  既然是包装原函数,就不能被改造;