21-Python 装饰器
简明python 装饰器介绍
简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
一般而言,我们要想拓展原来函数代码,最直接的办法就是侵入代码里面修改,例如:
这是我们最原始的的一个函数,然后我们试图记录下这个函数执行的总时间,那最简单的做法就是:
但是如果你的Boss在公司里面和你说:“这段代码是我们公司的核心代码,你不能直接去改我们的核心代码。”那该怎么办呢,我们仿照装饰器先自己试着写一下:
这里我们定义了一个函数deco,它的参数是一个函数,然后给这个函数嵌入了计时功能。然后你可以拍着胸脯对老板说,看吧,不用动你原来的代码,我照样拓展了它的函数功能。
然后你的老板有对你说:“我们公司核心代码区域有一千万个
func()函数,从func01()到func1kw(),按你的方案,想要拓展这一千万个函数功能,就是要执行一千万次deco()函数,这可不行呀,我心疼我的机器。
”好了,你终于受够你老板了,准备辞职了,然后你无意间听到了装饰器这个神器,突然发现能满足你的要求了。
我们先实现一个最简陋的装饰器,不使用任何语法糖和高级语法,看看装饰器最原始的面貌:
这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数
func()就在返回函数
wrapper()的内部执行。
然后在函数
func()前面加上
@deco,
func()函数就相当于被注入了计时功能,现在只要调用
func(),它就已经变身为“新的功能更多”的函数了。
所以这里装饰器就像一个注入符号:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。
然后你满足了Boss的要求后,Boss又说:“我让你拓展的函数好多可是有参数的呀,有的参数还是个数不定的那种,你的装饰器搞的定不?”然后你嘿嘿一笑,深藏功与名!
最后,你的老板说:“可以的,我这里一个函数需要加入很多功能,一个装饰器怕是搞不定,装饰器能支持多个嘛” 最后你就把这段代码丢给了他:
多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身。盗用别人的例子:
输出:
functools.wraps
Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:
from functools import wraps def a_new_decorator(a_func): @wraps(a_func) def wrapTheFunction(): print("在执行之前我在做一些无聊的工作 a_func()") a_func() print("在执行之后我在做一些无聊的工作 a_func()") return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): """Hey yo! 来装饰我有!""" print("我是需要一些装饰的功能 “除掉我的臭味 ") print(a_function_requiring_decoration.__name__) # Output: a_function_requiring_decoration
我的第一个装饰器
from functools import wraps def decorator_name(f): @wraps(f) def decorated(*args, **kwargs): if not can_run: return "函数将没有执行" return f(*args, **kwargs) return decorated @decorator_name def func(): return("函数执行") can_run = True print(func()) # 输出 函数执行 can_run = False print(func()) # 输出 函数将没有执行
注意:@wraps
接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。
这可以让我们在装饰器里面访问在装饰之前的函数的属性。
使用场景
•授权(Authorization):
from functools import wraps def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): auth = request.authorization if not auth or not check_auth(auth.username, auth.password): authenticate() return f(*args, **kwargs) return decorated
•日志(Logging):
from functools import wraps def logit(func): @wraps(func) def with_logging(*args, **kwargs): print(func.__name__ + " was called") return func(*args, **kwargs) return with_logging @logit def addition_func(x): """Do some math.""" return x + x result = addition_func(4) # Output: addition_func was called
•在函数中嵌入装饰器:
from functools import wraps def logit(logfile='out.log'): def logging_decorator(func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + " was called" print(log_string) # 打开logfile,并写入内容 with open(logfile, 'a') as opened_file: # 现在将日志打到指定的logfile opened_file.write(log_string + '\n') return func(*args, **kwargs) return wrapped_function return logging_decorator @logit() def myfunc1(): pass myfunc1() # Output: myfunc1 was called # 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串 @logit(logfile='func2.log') def myfunc2(): pass myfunc2() # Output: myfunc2 was called # 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串
sofiiii:https://www.jianshu.com/p/2b372d38fb3c
阿平搞Python:https://www.jianshu.com/p/95e04256264d
IT入门 感谢关注 | 程序员题库→ 程序员用的单词表→ 练习地址:www.520mg.com/it |
- Python高阶函数 filter 、排序、返回函数、闭包、装饰器、偏函数------21
- 老生常谈Python进阶之装饰器
- python知识点(5)-----------装饰器小结
- Python学习笔记--装饰器强化
- Python21_文件读写
- Python 装饰器
- Python 中的类装饰器 类似于JAVA中的annotation
- 一个有用的python装饰器 -- 为执行程序加锁
- python--装饰器(附偏函数、断言)
- 自学Python4.4-装饰器的进阶
- Python入门的36个例子 之 21 -> Dictionary —— 通过你的ID找到你
- Python 函数装饰器
- Python笔记(21)局部变量与全局变量作用域
- python利用装饰器进行运算的实例分析
- Python中的装饰器'@'符号
- 学习python(day11)(装饰器的讲解)
- Appium+python自动化21-DesiredCapabilities详解
- python-12带有参数的装饰器
- Python 装饰器学习以及实际使用场景实践
- python进阶_基础篇11(三大神器:装饰器、迭代器、生成器)