Python中的装饰器
-
概述
-
装饰器是修改其他函数的功能的函数
-
-
菜鸟教程讲述链接
-
示例
-
不使用@符号,直接调用装饰器函数
def wrapper(func):
def doSomethingBeforeHi():
print("I am doing some boring work before executing hi()")
print(func())
return doSomethingBeforeHi
def hi():
return "hi yasoob!"
a = wrapper(hi)
a()-
使用@符号代替调用装饰器的过程
-
优点:代码其他部分可依然调用原函数名称,实现调用装饰器的过程
-
问题:运行如下代码会存在一个问题,Ouput输出不是原函数的名字和注释文档
-
def wrapper(func):
a = 1
def hello():
nonlocal a
print('hello')
func()
a += 1
print(a)
print('good bye')
print(a+5)
return hello
6
hello
aaa
2
good bye
<function wrapper.<locals>.hello at 0x000001C6FF5EDE58>-
解决办法:使用functools.wraps函数,导入functools中的wraps。修改装饰器函数的代码如下 @wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性
from functools import wraps
def wrapper(func):
a = 1
<function tmp at 0x000002757F39DE58> -
-
装饰器使用场景
-
授权(Authorization):装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权:
from functools import wraps
def requires_auth(f):
-
日志(Logging):日志是装饰器运用的另一个亮点。这是个例子:
from functools import wraps
def logit(func):
-
-
带参数的装饰器
-
我们回到日志的例子,并创建一个包裹函数,能让我们指定一个用于输出的日志文件
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
-
-
装饰器类
-
将上述日志功能,改造为类的方式
-
优点:比嵌套函数的方式更加整洁,而且包裹一个函数还是使用跟以前一样的语法
from functools import wraps
class logit(object):
def __init__(self, logfile='out.log'):
self.logfile = logfile
def __call__(self, func):
-
还可以给logit 创建子类,来添加 email 的功能
class email_logit(logit):
'''
一个logit的实现版本,可以在函数调用时发送email给管理员
'''
def __init__(self, email='admin@myproject.com', *args, **kwargs):
self.email = email
super(email_logit, self).__init__(*args, **kwargs)
def notify(self):
# 发送一封email到self.email
# 这里就不做实现了
pass -
-
装饰器执行顺序
-
一个函数还可以同时定义多个装饰器,执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器
等效于:
f = a(b(c(f))) -
-
-
举例理解
-

浙公网安备 33010602011771号