一、注意装饰器函数所在的位置:
代码示例如下:
python
from flask import Flask
app = Flask(__name__)
def wapper(func):
def inner(*args, **kwargs):
print("执行了装饰器")
return func(*args, **kwargs)
return inner
@wapper
@app.route("/index1")
def index():
return "Index"
if __name__ == "__main__":
app.run()
执行结果:
由上述代码执行结果可知,装饰器wapper并没有被执行到,这是由于请求过来之后,执行完index并返回视图,因为wapper装饰器在app.route上面,所以并未执行到wapper装饰器,若想执行wapper装饰器,则需要将wapper放到route下面。
python
@app.route("/index1")
@wapper
def index():
return "Index"
执行结果如下:
由上述程序执行结果可知,当装饰器wapper放到route下面的时候,route会把装饰器wapper和index函数当做一个整体去执行,因此按照装饰器的执行顺序,就会先执行wapper返回inner函数引用,然后在执行请求,返回视图。
二、由第一条衍生出第二个问题,当多个请求共同被一个装饰器装饰的时候,程序会出现错误,示例及结果如下:
python
from flask import Flask
from werkzeug.routing import BaseConverter
app = Flask(__name__)
def wapper(func):
def inner(*args, **kwargs):
print("执行了装饰器")
return func(*args, **kwargs)
return inner
@app.route("/index1")
@wapper
def index():
return "Index"
@app.route("/index2")
@wapper
def index2():
return "Index"
if __name__ == "__main__":
app.run()
执行结果:
这是因为两个请求被一个装饰器装饰,执行装饰器后返回的是同样的inner函数的引用,因此存在两个inner函数,故而程序会报错,如果需要解决此问题就需要在执行装饰器的时候返回的函数引用是传入的函数参数,而不是内部闭包函数。因此需要在装饰器函数的内部函数上添加@functools.wraps(func)
@functools.wraps(func) (作用是在装饰函数时保留被装饰函数的元数据,比如函数名、注释、参数列表等。因为装饰器通常会改变函数的元数据,导致被装饰函数的某些特性丢失),代码如下所示:
python
def wapper(func):
def inner(*args, **kwargs):
print("执行了装饰器")
return func(*args, **kwargs)
return inner