当前位置: 首页 > news >正文

理解 Python 装饰器:@ 的强大功能

文章目录

  • 理解 Python 装饰器:`@` 的强大功能
    • 什么是装饰器?
    • 装饰器何时执行?
    • 装饰器实战:FastAPI
      • FastAPI 的 `@app.get`
      • FastAPI 的 `@app.on_event`
    • 关于装饰器的关键点
    • 结论

理解 Python 装饰器:@ 的强大功能

在 Python 中,@ 符号与**装饰器(Decorator)**紧密相关。装饰器是一种强大且灵活的工具,允许在不修改函数、方法或类源代码的情况下,扩展或修改其行为。本文将深入探讨装饰器的工作原理、执行时机以及实际应用,结合通用 Python 编程和 FastAPI 框架的示例。

什么是装饰器?

装饰器是一个高阶函数(或可调用对象),通过包装另一个函数或类来添加功能。Python 的 @ 符号是装饰器的语法糖,用于简洁地应用装饰器。例如:

def my_decorator(func):def wrapper():print("函数调用前")func()print("函数调用后")return wrapper@my_decorator
def say_hello():print("你好!")say_hello()

输出

函数调用前
你好!
函数调用后

在这里,@my_decoratorsay_hello 函数包装在一个 wrapper 函数中,添加了调用前后打印日志的功能。@ 语法等价于:

say_hello = my_decorator(say_hello)

装饰器何时执行?

装饰器的执行分为两个阶段:

  1. 代码解析阶段(模块加载时)
    • 当 Python 加载模块时,遇到 @decorator,会立即执行装饰器函数(例如 my_decorator),将目标函数(例如 say_hello)作为参数传递,并返回一个新的函数(例如 wrapper)。
    • 这一阶段负责装饰器的注册或配置
    • 示例:
import time
from functools import wrapsdef timer_decorator(func):print("解析时执行:注册装饰器")@wraps(func)def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)print(f"{func.__name__} 耗时 {time.time() - start_time:.2f} 秒")return resultreturn wrapper@timer_decorator
def slow_function():time.sleep(1)return "完成"print("正在解析代码...")
slow_function()

输出

解析时执行:注册装饰器
正在解析代码...
slow_function 耗时 1.00 秒
  • print("解析时执行:注册装饰器") 在模块加载时打印,表明装饰器的外层逻辑在解析时执行。
  1. 运行时阶段
    • 被包装的函数(wrapper)只有在调用被装饰函数(例如 slow_function())时才会执行。
    • 在上述示例中,wrapper 的计时逻辑(记录时间并打印)在 slow_function() 调用时运行。

装饰器实战:FastAPI

装饰器在 FastAPI 框架中被广泛用于路由和事件处理。以下是具体分析。

FastAPI 的 @app.get

在 FastAPI 中,@app.get 是一个装饰器,用于将函数绑定到特定的 HTTP 路由。例如:

from fastapi import FastAPIapp = FastAPI()@app.get("/hello")
@app.get("/v1/hello")
async def hello():return {"message": "你好!"}
  • 解析阶段
    • Python 解析代码时,@app.get("/hello")@app.get("/v1/hello") 调用 FastAPI.get 方法,进而调用 app.add_api_route,将 hello 函数注册到 app.routes 路由表,分别对应 /hello/v1/hello
    • 此时没有处理任何 HTTP 请求,装饰器仅完成路由配置。
  • 运行时阶段
    • 当收到 GET /helloGET /v1/hello 请求时,FastAPI 查询 app.routes,找到匹配的 hello 函数并直接调用。装饰器的逻辑(路由注册)不会再次执行。
  • 多个装饰器
    • 多个 @app.get 装饰器按从下到上的顺序应用:
      • @app.get("/v1/hello")hello 注册到 /v1/hello
      • @app.get("/hello")hello 注册到 /hello
      • 两个路由都指向同一个 hello 函数,请求任一路径都会触发它。

FastAPI 的 @app.on_event

FastAPI 曾使用 @app.on_event 装饰器来处理启动或关闭事件。例如:

@app.on_event("startup")
async def startup_event():print("应用启动...")
  • 解析阶段@app.on_event("startup") 调用 FastAPI.on_event,将 startup_event 注册到启动事件处理列表。
  • 运行时阶段:应用启动时,FastAPI 调用所有注册的启动事件函数。

注意@app.on_event 在 FastAPI 新版本中已废弃,推荐使用 lifespan 机制。例如:

from contextlib import asynccontextmanager@asynccontextmanager
async def lifespan(app: FastAPI):print("应用启动...")yieldprint("应用关闭...")app = FastAPI(lifespan=lifespan)

关于装饰器的关键点

  • 不限于函数:装饰器可以应用于函数、方法或类,只要它们是可调用对象(类需实现 __call__)。
  • 多个装饰器:多个装饰器按从下到上的顺序应用(由内向外)。例如:
@decorator1
@decorator2
def my_function():print("函数执行")
  • decorator2 先包装 my_functiondecorator1 再包装 decorator2 的结果。

  • 解析与运行时

    • 解析时:执行装饰器的外层逻辑(注册、配置)。
    • 运行时:执行包装逻辑(例如计时、路由处理)。
  • FastAPI 特性@app.get 在解析时注册路由(调用 app.add_api_route),运行时直接调用目标函数。

结论

Python 的 @ 装饰器是一种优雅的工具,能够增强代码的模块化和可重用性。无论是记录函数执行时间、注册 FastAPI 路由,还是实现权限控制,装饰器都提供了简洁的方式在不修改原始代码的情况下添加功能。

http://www.dtcms.com/a/446555.html

相关文章:

  • C++进阶(7)——包装器
  • Redis应用场景(黑马点评快速复习)
  • 泉州建站模板搭建深圳工业设计有限公司
  • 外贸出口工艺品怎么做外贸网站想自学做网站
  • 【Docker项目实战】使用Docker部署Dokuwiki个人知识库
  • 建设实验中心网站c2c网站价格
  • arp broadcast enable 概念及题目
  • 在搜狐快站上做网站怎么跳转做商品网站需要营业执照
  • 为什么多智能体系统需要记忆工程
  • C++:string 类
  • [crackme]019-CrackMe3
  • 宠物寄养网站毕业设计营销网站建设专业团队在线服务
  • C++11学习笔记
  • 搜狐快速建站郴州市做网站
  • 在Linux中重定向,复制cp,硬链接的区别,Linux底层存储数据原理。
  • 软考~系统规划与管理师考试—知识篇—V2.0—考试科目2:系统规划与管理案例分析—题型分类—第七章 IT 服务持续改进—20192021
  • NopGraphQL 的设计创新:从 API 协议到通用信息操作引擎
  • 概率论:分布与检验
  • 网站后台视频教程视频号怎么付费推广
  • 浦江网站建设微信开发wordpress 浏览计数
  • 嵌入式开发学习日志35——stm32之超声波测距
  • 山东建设厅官方网站一级建造师搜索引擎平台
  • MATLAB计算有效干旱指数(Effective drought index, EDI)
  • 网站推广如何收费现在建一个网站一年费用只要几百元
  • 如何自己做游戏网站如何建设万网网站
  • 江苏省建设厅八大员考试报名网站石家庄有哪些公司可以做网站
  • 搭建Jenkins gitlab 环境
  • 企业做的网站费入什么科目江西网站备案
  • pink老师html5+css3day05
  • 哪里找人做网站织梦淘客网站