Python 装饰器(Decorators)

  1. 什么是装饰器?
    装饰器(Decorator)本质上是一个 修改其他函数功能的函数。它的核心思想是:不修改原函数代码,动态添加新功能。比如:

记录函数执行时间

检查用户权限

缓存计算结果

自动重试失败操作

  1. 理解函数是“对象”
    在 Python 中,函数也是对象,可以像变量一样传递。这是装饰器的核心基础!
示例 1:函数赋值给变量
python
复制
def say_hello():print("Hello!")

将函数赋值给变量

greet = say_hello  

调用变量(实际调用函数)

greet()  # 输出: Hello!
示例 2:函数作为参数传递
python
复制
def call_twice(func):func()  # 第一次调用func()  # 第二次调用call_twice(say_hello)  
# 输出:
# Hello!
# Hello!
  1. 最简单的装饰器
    假设我们要在函数执行前后打印日志:

步骤 1:定义一个装饰器函数

python
复制
def log_decorator(func):def wrapper():print("函数开始执行...")func()  # 调用原函数print("函数执行完毕!")return wrapper  # 返回新函数

步骤 2:使用装饰器

python
复制
@log_decorator  # 语法糖(等价于 say_hello = log_decorator(say_hello)
def say_hello():print("Hello!")say_hello()# 输出:
# 函数开始执行...
# Hello!
# 函数执行完毕!
  1. 装饰器的执行过程
    当使用 @log_decorator 时,实际发生了以下步骤:

传递函数:log_decorator(say_hello) 被调用,参数是原函数 say_hello

返回新函数:log_decorator 返回内部定义的 wrapper 函数

替换原函数:say_hello 变量指向新的 wrapper 函数

  1. 处理带参数的函数
    如果被装饰的函数需要参数,怎么办?让 wrapper 接受参数并传递给原函数。

示例:记录函数参数

python
复制
def log_args(func):def wrapper(*args, **kwargs):  # 接受任意参数print(f"参数: args={args}, kwargs={kwargs}")return func(*args, **kwargs)  # 传递参数给原函数return wrapper@log_args
def add(a, b):return a + bprint(add(3, b=5))  
# 输出:
# 参数: args=(3,), kwargs={'b': 5}

8

  1. 装饰器带参数
    如果装饰器本身需要参数(比如指定日志级别),需要再包裹一层。

示例:根据日志级别打印

python
复制
def log_level(level):  # 外层函数接受参数def decorator(func):  # 装饰器函数def wrapper(*args, **kwargs):print(f"[{level}] 函数开始执行...")result = func(*args, **kwargs)print(f"[{level}] 函数执行完毕!")return resultreturn wrapperreturn decorator  # 返回装饰器@log_level("INFO")  # 等价于 add = log_level("INFO")(add)
def add(a, b):return a + badd(2, 3)
# 输出:
# [INFO] 函数开始执行...
# [INFO] 函数执行完毕!
  1. 保留原函数的信息
    使用装饰器后,原函数的名称(name)和文档(doc)会被替换为 wrapper。用 functools.wraps 解决这个问题:
python
复制
from functools import wrapsdef log_decorator(func):@wraps(func)  # 保留原函数信息def wrapper(*args, **kwargs):print("开始执行...")result = func(*args, **kwargs)print("执行完毕!")return resultreturn wrapper@log_decorator
def say_hello():"""打招呼的函数"""print("Hello!")print(say_hello.__name__)  # 输出: say_hello(而不是 wrapper)
print(say_hello.__doc__)   # 输出: 打招呼的函数
  1. 类装饰器
    除了函数,还可以用类实现装饰器。通过实现 call 方法:
python
复制
class CountCalls:def __init__(self, func):self.func = funcself.calls = 0def __call__(self, *args, **kwargs):self.calls += 1print(f"函数被调用了 {self.calls} 次")return self.func(*args, **kwargs)@CountCalls
def say_hello():print("Hello!")say_hello()  # 输出: 函数被调用了 1 次 → Hello!
say_hello()  # 输出: 函数被调用了 2 次 → Hello

!
9. 实际应用场景
装饰器在 Python 中广泛应用,例如:

Web框架:@app.route(“/”)(Flask/Django)

权限验证:@login_required

性能测试:计算函数执行时间

缓存:@lru_cache(内置装饰器)

总结
核心思想:装饰器通过“函数嵌套”和“函数作为参数”实现功能扩展。

关键点:

使用 @decorator 语法糖

处理参数:*args 和 **kwargs

保留原函数信息:@wraps(func)

类装饰器:实现 call 方法

试着写几个自己的装饰器(比如记录执行时间),就能快速掌握这个概念!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74856.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uWebSockets开发入门

一、常用C++ WebSocket开源库 一些常用的 C++ WebSocket 开源库,它们支持 WebSocket 协议的实现,适用于客户端或服务器端开发。 1. Boost.Beast (推荐) 特点:基于 Boost.Asio 的高性能库,支持 HTTP/WebSocket,属于 Boost 官方库的一部分,稳定且跨平台。 适用场景:需要高…

多智能体功能分化的核心优势是什么:提升效率,查漏补缺

多智能体功能分化的核心优势是什么:提升效率,查漏补缺 在于通过分工协作提升整体效率、灵活性和鲁棒性。 1. 提升效率与专业性 原理:单一智能体无需处理全流程,通过专业化分工减少冗余计算和决策延迟。 示例: 自动驾驶系统: 感知智能体:专门处理摄像头、激光雷达等传…

项目复盘:websocket不受跨域限制的原理

主要还是因为: 1、WebSocket 是独立于 HTTP 的应用层协议,通过 HTTP 建立连接后,完全脱离 HTTP 语义约束。这意味着 不受 HTTP 同源策略限制 不需要预检请求 不依赖 CORS 头机制 2、建立连接时的握手请求仍使用 HTTP 格式,但…

COMPASS:通过残差强化学习和技能合成实现跨具身移动策略

25年2月来自 Nvidia、UC Berkeley 和 UT Austin 的论文“COMPASS: Cross-embOdiment Mobility Policy via ResiduAl RL and Skill Synthesis”。 随着机器人越来越多地部署在不同的应用领域,可泛化的跨具身移动策略变得越来越重要。虽然经典的移动栈已被证明在特定…

无人机,雷达定点飞行时,位置发散,位置很飘,原因分析

参考: 无人车传感器 IMU与GPS数据融合进行定位机制_gps imu 组合定位原始数-CSDN博客 我的无人机使用雷达定位,位置模式很飘 雷达的更新频率也是10HZ, 而px飞控的频率是100HZ,没有对两者之间的频率差异做出处理 所以才导致无人…

学习threejs,使用Sprite精灵、SpriteMaterial精灵材质

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.Sprite1.1.1 ☘️代码…

外星人入侵(python设计小游戏)

这个游戏简而言之就是操作一个飞机对前方的飞船进行射击,和一款很久之前的游戏很像,这里是超级低配版那个游戏,先来看看效果图: 由于设计的是全屏的,所以电脑不能截图。。。。 下面的就是你操控的飞船,上面…

什么是CMS?常用CMS有哪些?

一、内容管理系统(Content Management System)‌ ‌什么是CMS‌:位于 Web 前端(服务器)和后端办公系统之间的软件系统,用于内容创建、编辑、审批和发布。支持文本、图片、视频、数据库等各类数字内容的管理…

Go 语言规范学习(3)

文章目录 Properties of types and valuesRepresentation of valuesUnderlying types【底层类型】Core types【核心类型】Type identityAssignabilityRepresentabilityMethod sets BlocksDeclarations and scopeLabel scopesBlank identifierPredeclared identifiersExported i…

在 Ubuntu 上安装 Docker 的完整指南

1. 卸载旧版本(如有) 在安装新版本前,建议先卸载旧版本: sudo apt remove docker docker-engine docker.io containerd runc 2. 安装依赖包 更新软件包索引并安装必要的依赖: sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release 3. 添加 Do…

turtle的九个使用

一 import turtle as t color [red,green,blue,orange,pink] for i in range(len(color)):t.penup()t.goto(-20070*i,0)t.pendown()t.pencolor(color[i])t.circle(50, steps 5) t.done()二 #在____________上补充代码 #不要修改其他代码import random as r import turtle a…

23种设计模式-备忘录(Memento)设计模式

备忘录设计模式 🚩什么是备忘录设计模式?🚩备忘录设计模式的特点🚩备忘录设计模式的结构🚩备忘录设计模式的优缺点🚩备忘录设计模式的Java实现🚩代码总结🚩总结 🚩什么是…

利用虚拟化技术实现高级Hook

虚拟化技术为系统监控和Hook提供了更强大、更隐蔽的实现方式。以下是几种基于虚拟化的Hook技术实现方法: 1. 基于VT-x/AMD-V的硬件虚拟化Hook 基本原理 利用CPU的硬件虚拟化扩展(Intel VT-x/AMD-V)在Ring -1层级监控系统行为,实现无法被常规方法检测的…

某鱼、某宝 sign 签名算法分析记录

【作者主页】:小鱼神1024 【知识星球】:小鱼神的逆向编程圈 【擅长领域】:JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 本文章中所有内容仅供学习交流使用,不用于其…

Compose笔记(十三)--事件总线

这一节了解一下Compose中的事件总线,在Jetpack Compose里,官方没有直接提供事件总线,但可以借助第三方库或者自定义实现来达成事件总线的功能,进而在不同的 Compose 控件间同步数据。 自定义事件总线 import androidx.compose.r…

Python的inspect模块

在Python编程中,**inspect**模块是一个强大的工具包,它提供了一系列函数来获取对象的信息,主要用于获取对象的源代码、参数信息、类继承关系、方法属性等。这对于调试、自动化文档生成、代码分析等场景都非常有用。本文将详细介绍inspect模块…

2025跳槽学习计划

(1)编程基础: 目录学习资料Chttps://www.bilibili.com/video/BV1z64y1U7hs?spm_id_from333.1387.favlist.content.clickLinuxPytorchhttps://www.bilibili.com/video/BV1if4y147hS?spm_id_from333.1387.favlist.content.clickopencv数据结…

WebRTC简介及应用

WebRTC(Web Real-Time Communication)是一种支持浏览器和移动设备进行实时音视频通信的技术,无需安装插件或额外的软件。它是一个开放标准,最初由Google推动,并被W3C(万维网联盟)和IETF&#xf…

【C语言】分支与循环(上)

前言:C语言是由顺序结构、选择结构、循环结构组成的结构化的程序设计语言。 那C语言是如何设计和实现这些结构的呢?话不多说,马上开始。 三种结构如图所示: 我们可以使用 if else语句、 switch语句 来实现选择(分支&am…

一次与chatgpt关于VO的深入讨论。

我: {"usageRate":50,"projectInfo":[{"productName":"长江一号","deviceInfo":[{"deviceName":"AA","num":10},{"deviceName":"BB","num":3}]},…