Python装饰器
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Python装饰器,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2510字,纯文字阅读大概需要4分钟。
内容图文
Python装饰器
一个生动的比喻是,被装饰函数是画作,而装饰器就是外面的画框。装饰器为被装饰函数提供额外的功能和行为;可以提取多个函数的共同部分作为装饰器,从而使代码更加清晰。
学习装饰器要逐步解决的问题:
- 如何定义,使用装饰器?装饰器的执行顺序如何?
- 装饰器的接口是怎么样的?被装饰函数及其参数是如何传递的?
- 装饰器的高级用法:参数化装饰器和类装饰器
装饰器的基本知识
装饰器的参数是被修饰的函数,在执行完额外工作后,要返回被装饰函数或另一个函数。
# 装饰器定义 def d1(func): print("decorator_1") return func # 放置装饰器@d1 def func(n) print(n)
上面的代码中,执行func()这个函数等价于 func = d1( func),也就是说,执行代码时,func是被d1装饰的结果的引用,不是原始的func。f = func(100),print(f)和print(func)结果不一样。
装饰器另外一个关键特性是:在加载模块时,他们在被装饰的函数定义之后立即执行,可见下面的代码:
def decorator_1(func): def miao(func): print("fck you, return func") return func print("decorator_1, return miao") return miao def decorator_2(func): print("decorator_2, return func") return func #叠放装饰器,结果等价于d1( d2( func_1))@decorator_1 @decorator_2 def func_1(val): print(val) if__name__ == "__main__": print("Main()") func_1(1000)
执行结果为:
decorator_2, return func decorator_1, return miao Main() fuck you, return func
这说明d2,d1两个装饰器在真正的被装饰函数func调用前,被执行。假如d2装饰了n个函数,那么d2要先执行n次。
参数传递
通常,装饰器内部定义了函数,这个内部函数执行额外的工作。这种结构涉及“闭包”的概念。所谓闭包,就是那些可以使用非全局变量、非自身的变量的函数,例如一个函数1内部定义了函数2,函数2可以使用函数1的变量,那么函数2就是一个闭包。
# 《Fluent Python》page 165 example-7-15 import time def clock(func): def clocked(*args): # ??# extra .. result = func(*args) return result return clocked
那么这里就有问题了:
Q1:*args是谁的参数?
从上下文中可知*args应该是func接受的函数,但是在上文装饰器的定义中,没有显式看到*args。由此推测:装饰器中的*args, **kwargs这些容器分别存放了被修饰函数func的positional args 和 keyword args。
Q2:上面的假设基于di(func)的,如果改为d1(func, *args, **kwargs),那么这两个容器放的是谁的参数?
ans:经过尝试,发现会抛出异常。如果写:
- @d1(**dict1), d1()missing a required positional arg ‘func‘.
- @d1(kwargs=dict1) , d1()missing a required positional arg ‘func‘.
- @d1(func=func_1, kwargs=dict1), name ‘func_1‘ is not defined.
通过查看他人代码实例,发现每个装饰器及其内部的函数,都有一个函数只有func一个参数。在《Fluent Python》page 76 example-7-25的注释中,第二条注释写道:decorate(func)是真正的函数。 第一条注释:clock(...)是装饰器工厂函数。所以在Q2中,d1这个入口不是真正的装饰器,装饰器的参数只有一个func。
下面的代码很有趣:
dict1 = { "name":"miao", "type":"zhizhi" } dict2 = { "name":"guagua", } def decorator_1(**kwargs): def miao(func): def zhi(**kwargs): for k,v in kwargs.items(): # 打印dict1print(k, v) return func return zhi for k,v in kwargs.items(): # 打印dict2print(k, v) print("decorator_1, return miao") return miao #d1( d2(func_1(1000))) @decorator_1(**dict2) def func_1(**kwargs): print("fuck") if__name__ == "__main__": func_1(**dict1)
d1接受的是dict2, func_1的参数是dict1, 最终逐个打印出来的是dict1的key-value,也就是说:miao(func)是真正的装饰器,其内部函数使用的**kwargs, *args都是被装饰函数的参数,作为工厂函数的d1,它接受的参数是外部直接传给的,区别于func的参数。
参数化装饰器
原文:https://www.cnblogs.com/Tsuko/p/9501061.html
内容总结
以上是互联网集市为您收集整理的Python装饰器全部内容,希望文章能够帮你解决Python装饰器所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。