关于python装饰器实现的一点疑问( 三 )
同时,我们再提炼一下这里面的几个重难点:
第一,requires_ints中,decorated这个变量是内嵌作用域的变量,在他调用退出后,返回的inner函数是可以记住这个变量的。
第二,python不支持函数的参数列表的多态,即一个函数名只能对应唯一的参数列表形式。
第三,在内嵌函数内部调用被装饰函数的时候,使用了解包参数,关于这*args, **kwargs,的参数形式,前面章节中细讲过。
那我们也用这个装饰器来装饰一个函数。@requires_intsdef foo(x,y): print(x+y)foo(3,5)8 这里将名称foo赋给inner函数,而不是赋给原来被定义的函数,如果运行foo(3,5),将利用传入的这两个参数运行inner函数,inner函数执行类型检查,然后运行被装饰方法,如果传入的不是整形数,例如下面这个例子,那么装饰器的附加功能就会进行类型检查:@requires_intsdef foo(x,y): print(x+y)foo(\u0026#39;a\u0026#39;,5)Traceback (most recent call last): File "E:/12homework/12homework.py", line 15, in \u0026lt;module\u0026gt; foo(\u0026#39;a\u0026#39;,5) File "E:/12homework/12homework.py", line 7, in innerraise TypeError(\u0026#39;{} only accepts integers as arguments\u0026#39;.format(decorated.__name__))TypeError: foo only accepts integers as arguments 其次内嵌的函数和被装饰的函数的参数形式必须完全一样,这里用的*args, **kwargs概况函数参数的一般形式,因此也是完全对应的。
最后说说装饰器参数
最后来介绍这个复杂一些的话题,装饰器参数。之前我们列举的常规例子里,装饰器只有一个参数,就是被装饰的方法。但是,有时让装饰器自身带有一些需要的信息,从而使装饰器可以用恰当的方式装饰方法十分有用。
这些参数并不是和被装饰的函数并列作为参数签名,而是在原有装饰器的基础上额外再增加一层封装,那么,实质是这个接受其他参数的装饰器并不是一个实际的装饰器,而是一个返回装饰器的函数。
最终返回的内嵌函数inner是最终使用indent和sort_keys参数的函数,这没有问题import jsondef json_output(indent=None, sort_keys=False): def actual_decorator(decorated): def inner(*args, **kwargs): result = decorated(*args, **kwargs) return json.dumps(result, indent=indent, sort_keys=sort_keys) return inner return actual_decorator@json_output(indent=8)def do_nothing(): return {\u0026#39;status\u0026#39;:\u0026#39;done\u0026#39;,\u0026#39;func\u0026#39;:\u0026#39;yes\u0026#39;}print(do_nothing()){ "status": "done", "func": "yes"}我们在这里详细解释说明的是操作顺序,看上去我们使用的是@json_output(indent=8),作这和之前的装饰器语法糖看上去有些不同,实际上这个不是最终的装饰器函数,通过调用json_output(indent=8),返回函数指针actual_decorator,这个函数才是真正放在@后的装饰器函数,原始的被装饰函数最终获得了内涵更丰富的inner函数对象,完成了装饰过程,值得一提的是,所谓的装饰器参数最终传给了最内层的inner函数。
记住,在定义装饰器函数后,真正的装饰器函数只有一个参数,那就是被装饰的函数指针,而有其他参数的函数实质上只是装饰器的外围函数,他可以依据参数对装饰器进行进一步的定制。一句话:一个函数不可能接受被装饰的方法,又接受其他参数
在语法糖中@func这种不带括号的,就是直接使用装饰器函数进行装饰,如果是@func()带括号的,实质上是先调用func()函数返回真正的装饰器,然后再用@进行调用。
推荐阅读
- 过节■江苏省委省政府办公厅下发关于做好2021年元旦春节期间有关工作的通知
- 怎样成为一名合格的Python程序员?
- |徐州市出台《关于优化创新创业生态系统 提升区域科技创新活力的实施意见》及实施细则
- 雨下|全球关于禁售燃油车只是理论上可行吗
- python 爬虫,咋获得输入验证码之后的搜索结果
- 关于用phpfsocket 写Post, 模拟http 报文怎样写入要传输的处理数据
- 智叔|很多家长还在整箱买:谈谈关于牛奶的17个真相警惕这些列入黑名单的“假牛奶”
- python的html5lib这个库咋使用啊我在网上也没有找到相关文档
- 关于微信小程序的思考:运营者该何去何从
- 关于人工智能虚拟人的一些问题
