python中装饰器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37653394/article/details/82969324

看完廖雪峰的python教程中的装饰器部分,对装饰器深有体会了。

装饰器(Decorator),他确实是起装饰作用的,而且是装饰函数的(好像也可以装饰类,不过还没学,见谅),不过不是让函数看起来更加好看的,而是对函数添加一些额外功能的,这也是一种装饰。

先来看一段代码:

In [152]: def log(func):
     ...:     def wrapper(*args, **kwargs):
     ...:         print("call {}()".format(func.__name__))
     ...:         return func(*args, **kwargs)
     ...:     return wrapper
     ...:
     ...:

这里的log函数就是一个装饰器,它接受一个函数作为参数,同时返回一个wrapper函数。

但是其实内部的wrapper函数才是真正起修饰功能的部分,它可以接受任意参数,因此也当wrapper函数被返回后被重新调用时可以接受func函数的所有需要的参数。

warpper函数中的参数就是传递给func函数用的,但是wrapper函数不知道func函数需要什么参数,因此接受任意参数。

在wrapper函数内部,print语句这一行,就相当于对func函数添加的额外功能,但是又没有改变func函数的内部结构,只是在外部改变的;return这一行,执行了真正的func的功能,并且返回了执行后的值。这也让wrapper函数在后面的重新调用中真正模拟了func的作用(执行同样的功能,有同样的返回值),但是添加了额外的功能。

在python中使用@语法,可以间装饰器放在函数定义的前面。如下:

In [153]: @log
     ...: def multi(n):#计算从1到n的累乘(阶乘)
     ...:     return functools.reduce(lambda x,y:x*y, range(1,abs(n)))
     ...:
     ...:

在函数定义前面加上 @log 相当于:

multi = log(multi)

log是一个Decorator,它接受一个函数,同时也返回一个函数。

这里相当于使用一个同名变量multi指向了新函数,原来的multi函数还在。

因此在我们执行multi(n)时,已经不是原来的multi函数了(其实是装饰器内部的wrapper函数,这个multi中的n就是传递给原来multi函数中的n),但是和原来的函数拥有相同的功能,而且多了额外的功能(print了一下...)

In [154]: result = multi(10)
call multi()

In [155]: result
Out[155]: 362880

猜你喜欢

转载自blog.csdn.net/qq_37653394/article/details/82969324
今日推荐