教小姐姐学习python-S01E22神奇的装饰器
【先导语】
1.神奇的装饰器到底是什么
2.装饰器的用法和语法糖
3.装饰器如何添加参数
装饰器是python里的一个非常有意思的部分,他用于封装函数代码,显式的将封装器应用到被封装的函数上,从而使得他们选择加入到装饰器指定的功能中。对于在函数运行前处理常见前置条件(例如确认授权),或在函数运行后确保清理(输出清除或异常处理),装饰器都非常有用。
【小姐姐】听不明白,太绕了!
简单来说,装饰器就是实现了一个通用的功能,然后将这个通用的功能应用到不同的、需要使用这个功能的函数上,从而避免每次都在不同函数上反复写相同的功能代码。
装饰器的本质是一个函数,他接受被装饰的函数作为位置参数,装饰器通过使用该参数来执行某些操作,然后返回一个函数引用,这个函数可以是原始函数,或者是另外一个函数。
我们举例子说明,装饰器是这样的函数,他们接受被装饰的可调用函数作为唯一的参数,并且返回一个可调用函数,
register方法是一个简单的装饰器,它把被装饰的函数添加到一个列表中,然后这里是将未改变的被装饰函数返回,可以看出,装饰器一般是传入被装饰函数的引用,然后经过一些指定的处理,最后返回值也是一个函数引用。
还有一种更简单的语法形式:
装饰器的语法糖:我们这里看到的对foo进行装饰的方法是运用
foo = register(foo)语句,还有一种简单的用法是在声明函数的位置应用装饰器,从而使得代码更容易阅读,并且让人立刻意识到使用了装饰器
同时,我们再提炼一下这里面的几个重难点:
第一,requires_ints中,decorated这个变量是内嵌作用域的变量,在他调用退出后,返回的inner函数是可以记住这个变量的。
第二,python不支持函数的参数列表的多态,即一个函数名只能对应唯一的参数列表形式。
第三,在内嵌函数内部调用被装饰函数的时候,使用了解包参数,关于这*args, **kwargs,的参数形式,前面章节中细讲过。
【小姐姐】那我们也用这个装饰器来装饰一个函数。
这里将名称foo赋给inner函数,而不是赋给原来被定义的函数,如果运行foo(3,5),将利用传入的这两个参数运行inner函数,inner函数执行类型检查,然后运行被装饰方法,如果传入的不是整形数,例如下面这个例子,那么装饰器的附加功能就会进行类型检查:
其次内嵌的函数和被装饰的函数的参数形式必须完全一样,这里用的*args, **kwargs概况函数参数的一般形式,因此也是完全对应的。
最后说说装饰器参数
最后来介绍这个复杂一些的话题,装饰器参数。之前我们列举的常规例子里,装饰器只有一个参数,就是被装饰的方法。但是,有时让装饰器自身带有一些需要的信息,从而使装饰器可以用恰当的方式装饰方法十分有用。
这些参数并不是和被装饰的函数并列作为参数签名,而是在原有装饰器的基础上额外再增加一层封装,那么,实质是这个接受其他参数的装饰器并不是一个实际的装饰器,而是一个返回装饰器的函数。
最终返回的内嵌函数inner是最终使用indent和sort_keys参数的函数,这没有问题
我们在这里详细解释说明的是操作顺序,看上去我们使用的是@json_output(indent=8),作这和之前的装饰器语法糖看上去有些不同,实际上这个不是最终的装饰器函数,通过调用json_output(indent=8),返回函数指针actual_decorator,这个函数才是真正放在@后的装饰器函数,原始的被装饰函数最终获得了内涵更丰富的inner函数对象,完成了装饰过程,值得一提的是,所谓的装饰器参数最终传给了最内层的inner函数。
q群 519970686 资料分享
记住,在定义装饰器函数后,真正的装饰器函数只有一个参数,那就是被装饰的函数指针,而有其他参数的函数实质上只是装饰器的外围函数,他可以依据参数对装饰器进行进一步的定制。一句话:一个函数不可能接受被装饰的方法,又接受其他参数