0


(三)Flask前置知识栈——装饰器

  • 在后续的讲解中,对大家对装饰器的掌握程度要求较高,所以此文来深入讲解一下,有看过《Python全栈系列教程》专栏的小伙伴可能会说,装饰器已经出过文章讲的很详细了。饶是如此,深究过装饰器的小伙伴们就权当复习一遍,同时,本篇文章会有所拓展哦~
  • 在继续之前,请确保您对函数和闭包的概念有一定的了解,因为这些是理解装饰器的基础知识。详见:《20.Python函数(五)【函数式编程 上半篇】》和《21.Python函数(六)【函数式编程 下半篇】》。

深究Python——装饰器

三个问题:

  1. 什么是装饰器?
  2. 手写装饰器?
  3. 装饰器都在哪里使用过或者说是见到过?

1. 什么是装饰器?

或者说为什么要用装饰器?

  • 在 Python 中,装饰器是一种特殊的语法,为已有的对象添加额外的功能。装饰器本质上是一个 Python 函数或者类,它可以将其它函数或类作为参数或者返回值。装饰器的作用是在不改变被装饰对象源代码的情况下,添加额外的功能。

使用装饰器的好处:

  1. 代码重用:装饰器可以在多个函数或类之间重复使用,避免代码冗余。
  2. 动态增加功能:通过装饰器,可以在运行时动态地给对象增加新的功能或修改已有功能。例如,在 Flask 中,很多常见的功能都是通过装饰器实现的,比如身份验证、路由注册等。
  3. 简化代码结构:装饰器可以将一些通用的代码逻辑抽象出来,避免在每个函数中都写一遍相同的代码。这样可以让代码结构更清晰,易于维护。
  4. 提高代码可读性:装饰器可以把一些额外的逻辑和代码与源代码分离,让源代码更加简洁易懂。
  5. 解耦代码:通过装饰器,可以将不同的逻辑分离,减少代码之间的耦合。
  • 总之,装饰器是 Python 中非常强大和灵活的一种功能,可以简化代码结构、提高代码可读性和可维护性,并在不改变源代码的情况下为代码动态增加新的功能。因此,装饰器非常流行,在 Python 中被广泛使用。

2. 手写装饰器?

  • 下面是一个基础的函数:
defindex(a1):return a1 +1000# 执行函数
v = index(2)print(v)# 获取函数名print(index.__name__)

在这里插入图片描述

  • 手写装饰器:
# 装饰器defwapper(func):definner(*args,**kwargs):return func(*args,**kwargs)return inner
  • 使用装饰器:
"""
@语法糖的作用:
1.看见@wrapper,执行wapper函数,并将被装饰的函数当做参数传递进去,即 wapper(index)
2.将第一步的返回值,重新赋值给 新index = wapper(老index)
"""# 使用@wapperdefindex(a1):return a1 +1000

v = index(999)print(v)print(index.__name__)# 这里输出就不是index而是inner了,说明了上述说的第二步,即函数被重新赋值了
  • 引出一个问题:
@wapperdefindex(a1):return a1 +1000@wapperdeforder(a1):return a1 +1000# 下面输出都是innerprint(index.__name__)print(order.__name__)
  • 触发需求——当函数被装饰后,依然想通过__name__获取原函数的名字?
  • 解决方法——在装饰器中使用内置的functools.wraps()
import functools

defwapper(func):@functools.wraps(func)definner(*args,**kwargs):return func(*args,**kwargs)return inner
    
# 将装饰器改成这样之后,上面那俩输出一个是index,一个是order

functools.wraps()这个装饰器的实现原理:

  • 首先,每个函数都有自己的元信息(函数名/注释等),而functools.wraps()装饰器就会将原来函数(func)的元信息赋值给函数(inner)。

3. 装饰器都在哪里使用过或者说是见到过?

毋庸置疑,在这个专栏里写这篇文章,那就是Flask里使用过装饰器。其实前面每次注册路由,不都是用的装饰器吗?

  • 直接看Flask中使用自定义装饰器:
from flask import Flask
from functools import wraps

app = Flask(__name__)defwapper(func):@wraps(func)definner(args,**kwargs):print('before')return func(args,**kwargs)return inner

@app.route('/xxx')@wapperdefindex():return'Index'@app.route('/aaa')@wapperdeforder():return'Order'if __name__ =='__main__':
    app.run()

注意点:

  1. 为了保证请求每次进来,装饰器都能执行,所以加的装饰器一定要在route下面;
  2. endpoint默认为函数名,不能有同名的(会报错),所以一定要使用functools的wraps装饰器。

装饰器——进阶:

下面是网上摘录的一段代码,看看你能否看懂为何会是这种输出顺序(里面附带注释):
欢迎在评论区留下你的思考痕迹~
【感觉有必要多出几篇,深入讲一下装饰器,敬请期待~】

defwrapper1(func):# func ==  f函数名    #哪个糖靠近被装饰函数,哪个语法糖函数就先执行,但是内部的inner却后执行print('进入wrapper1了')definner1():print('inner1')# 2
        func()# 这个函数func是被装饰的函数print('func1')# 4return inner1  # @wrapper1最后一句f==inner1和@wrapper2后第一句f=wrapper2(f),变量替换,inner1 = wrapper2(f),这样就执行下面的装饰器函数了defwrapper2(func):# func == inner1   上面返回一个inner1 = wrapper2(f)print('进入wrapper2了')definner2():print('inner2')# 1
        func()# 这里的func()其实是inner1(),到上面去了print('func2')# 5return inner2

@wrapper2# f = wrapper2(f)  里面的f==inner1  外面的f == inner2@wrapper1# f = wrapper1(f)   里面的f==函数名f  外面的f == inner1deff():# 3print('主函数')

f()# inner2()

在这里插入图片描述

标签: flask 数据库 python

本文转载自: https://blog.csdn.net/qq_44907926/article/details/131506552
版权归原作者 孤寒者 所有, 如有侵权,请联系我们删除。

“(三)Flask前置知识栈——装饰器”的评论:

还没有评论