装饰器在不修改原函数定义的情况下,增强了原函数的功能。这种在代码执行期间动态添加函数的方式称为装饰器。装饰器本质上是一个返回函数的高阶函数。在了解装饰器之前,我们先简单介绍一下返回函数的相关内容。在返回函数之前,我们讲了高阶函数,比如map()和filter()函数,它们可以接受函数作为参数,函数也可以作为结果值返回。首先定义一个简单的函数:>>>deffunc():...print("returnfunction")上面的代码只是一个普通的函数。如果不需要立即输出,可以返回函数而不是直接输出:>>>defreturn_func():...deffunc():...print("returnfunction")...returnfunc调用return_func()时,返回的不是输出结果,而是函数:>>>f=return_func()>>>f.funcat0x000002C03AF091E0>调用f时,内容为output:>>>f()返回函数这是返回函数的简单应用。Closure闭包是指在一个函数内部定义了另一个函数,内部函数是指外部函数的参数和局部变量。内部函数返回时,相关参数和变量存储在返回函数中。下面的代码实现了闭包操作:>>>deflazy_sum(*args):...defsum():...num=0...forxinargs:...num+=x..。returnnum...returnsum...在这个例子中,内部函数调用外部函数的参数args。调用lazy_sum时,返回的函数存储相关的参数和变量。只有再次调用返回函数,才会得到运算结果。>>>f=lazy_sum(1,2,3,4,5)>>>f.sumat0x000002C03AF31488>>>>f()15这里需要注意的是每次外部函数被调用,返回的函数都是新函数,即使传入的参数相同:>>>f1=lazy_sum(1,2,3,4,5)>>>f2=lazy_sum(1,2,3,4,5)>>>f1isf2False>>>f1==f2False在此示例中,f1()和f2()的结果不会相互影响。另外需要注意的是return函数并不是立即执行的,而是在调用f()之后执行的。尝试用另一个例子来说明这种情况,如下:>>>defcount():...lst=[]...foriinrange(1,4):...deffunc():...returni*i...lst.append(func)...returnfunc...>>>f1,f2,f3=count()在此示例中,每次通过循环,都会创建一个新函数,它返回创建的3个函数。这里的结果可能会猜测调用f1()、f2()、f3()的结果分别是1、4、9,但实际结果都是9:>>>f1()9>>>f2()9>>>这里的f3()9是因为返回的函数引用了变量i,但是并没有立即执行。当三个函数都返回的时候,引用的变量i的值都变成了3,所以最后的结果是9。所以,在返回闭包的时候,返回函数不应该引用循环变量,或者会改变的值之后。装饰器如前所述,装饰器本质上是一个返回函数的高阶函数。尝试用例子来说明,>>>deflog(func):...defwarpper(*args,**kw):...print('call{}():'.format(func.__name__)...returnfunc(*args,**kw)...returnwrapper上面的log是一个装饰器,接受一个函数作为参数,返回一个函数,借助Python的@语法,将装饰器放在定义处函数的:@logdeffunc():print("函数名")调用func()函数,会运行func()本身的函数,在运行func()之前还会打印一行日志:>>>func()callfunc():functionname这里在func()函数的定义处加上@log,相当于下面的语句:func=log(func)由于log()是一个装饰器,所以返回一个函数,但是原来的func()仍然存在,只是同名的func()现在指向了新的函数,所以调用func()时,会执行wrapper()函数。wrapper()函数,先打印log,再打印原始函数被调用。以上是装饰器的一些内容,至于更深入的部分,后面会继续更新介绍。以上是本文的主要内容。题外话:最近网络上流传着很多谣言,导致很多人无法正确辨别真假。下面链接是腾讯新闻的一个平台【比真】,实时为大家辟谣科普,可以帮助大家辨别真伪。尽量不要传播谣言或相信谣言。https://vp.fact.qq.com/home欢迎关注微信公众号《书所集录》