Python 函数装饰器
装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。
一切皆为对象
对于python中的函数:
1 | def hi(name="you"): |
在函数中定义函数
函数中的函数属于私有函数,外部无法直接调用
1 |
|
从函数中返回函数
当将函数名本身作为返回值时 a=f
,则是将函数地址返回,并不是调用函数,而如果将函数赋值给变量a=f()
,则是将f()
的返回值赋值给a的过程
1 |
|
在上述代码中,使用 判断语句返回了 greet
和 welcome
,而不是greet()
和 welcome()
,那么上面的a()
和b
的结果就是一样的。
将函数作为参数传给另一个函数
1 |
|
当函数为变量名时,指向地址 可将函数本身作为参数传向函数调用。
那么装饰器的用法就出现了,可以将函数本身插入某段代码之中。(类似jvav中spring框架的依赖注解)
实例
1 | def a_new_decorator(a_func):#定义装饰器 |
我们用装饰器封装了一个函数,那么我们可以用@
来进行注解注入
1 |
|
@a_new_decorator
相当于a=a_new_decorator(func1)
那么注解@就相当于将当前函数注入装饰器中,那么调用当前这个函数,就是将当前函数装饰后返回结果。
但是此时要注意
1 | print(func1.__name__) |
对于正常函数来说,应该返回函数本身的名称即func1
这里的函数被warpTheFunction替代了。它重写了我们函数的名字和注释文档(docstring)。幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:
1 | from functools import wraps |
蓝本规范:
1 | from functools import wraps |
注意:@wraps
接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
关于*args,**kwargs的小知识
答:可变参数
- 如果我们不确定要往函数中传入多少个参数,或者我们想往函数中以列表和元组的形式传参数时,那就使要用
*args
, 输出结果以元组的形式展示 ; - 如果我们不知道要往函数中传入多少个关键词参数,或者想传入字典的值作为关键词参数时,那就要使用
**kwargs
,它将打包关键字参数成dict给函数体调用, 输出结果以列表形式展示 。
1 | L=(1,2,[1,2,3]) |
使用场景
授权(Authorization)
装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权:
1 | from functools import wraps |
日志(Logging)
1 |
|
带参数的装饰器
在函数中嵌入装饰器
1 |
|
装饰器类
1 | from functools import wraps |
从现在起,@email_logit 将会和 @logit 产生同样的效果,但是在打日志的基础上,还会多发送一封邮件给管理员。
被面试官问到的悲惨经历,就突然想不起来了~~