Python学习2---装饰器

news/2024/9/13 0:35:23/ 标签: python, 学习, 装饰器

装饰器是Python中的一种高级功能,允许您修改或增强函数或类的行为,而无需直接修改其源代码。

基本概念:
装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。

基本语法:

python">@decorator_function
def target_function():pass

等同于:

python">def target_function():pass
target_function = decorator_function(target_function)

一、简单装饰器示例
1、函数装饰器

python">def simple_decorator(func):def wrapper():print("函数开始执行...")func()print("函数执行完成!")return wrapper@simple_decorator
def hello():print("hello world")hello()输出:
函数开始执行...
hello world
函数执行完成!

解析:simple_decorator 就是一个装饰器。它接受一个函数 func 作为参数,并返回一个新的函数 wrapper。当使用 @simple_decorator 语法糖在 hello 函数上应用装饰器时,实际上是调用了 simple_decorator(hello),返回了 wrapper 函数,然后当你执行 hello() 时,实际上是执行了 wrapper()。

2、带参数的函数装饰器
装饰器可以通过在 wrapper 函数中使用 *args 和 **kwargs 来处理这个问题。

python">def decorator_with_args(func):def wrapper(*args, **kwargs):print("参数:", args, kwargs)func(*args, **kwargs)return wrapper@decorator_with_args
def greet(name, message="Hello"):print(f"{message}, {name}")greet("Python")

当原始函数(如 greet)需要接受参数时,装饰器内的 wrapper 函数需要能够接收任意数量的位置参数 (*args) 和关键字参数 (**kwargs)。

• *args 和 **kwargs :这两个特殊的参数用于让 wrapper 函数能接受任意数量和类型的参数,从而使装饰器更加通用。*args 用于未命名的参数(位置参数),而 **kwargs 用于命名参数(关键字参数)。

• func(*args, **kwargs) 调用 :这确保了无论原始 greet 函数需要哪些参数,wrapper 都能传递正确的参数给它。

如下:

3、装饰器带参数
有时候你可能希望装饰器本身能接受一些参数。为了实现这个功能,你需要再加一层包装。

python">def repeat_decorator(times):def decorator(func):def wrapper(*args, **kwargs):for _ in range(times):result = func(*args, **kwargs)return resultreturn wrapperreturn decorator@repeat_decorator(3)
def greet(name):print(f"Hello, {name}!")greet("Alice")  # 将打印 3 次 "Hello, Alice!"

这个例子展示了如何创建一个带参数的装饰器装饰器 repeat_decorator接受一个参数 times=3,表示需要重复执行原始函数 func 的次数。

外层函数 repeat_decorator(times):这是装饰器的外层,负责接受装饰器的参数(在这里是 times),并返回一个装饰器函数 decorator。

中层函数 decorator(func):这是实际的装饰器函数,负责接收目标函数 func 并返回 wrapper 函数。

内层函数 wrapper(*args, **kwargs):这是包裹目标函数 func 的函数,它通过 *args 和 **kwargs 接受任意数量和类型的参数,并根据外层 repeat_decorator函数的参数 times 决定执行 func。

二、装饰器的高级用法
1. 类作为装饰器
装饰器利用了Python的 call 方法,使得类的实例可以像函数一样被调用;
Python 中的装饰器不仅可以是函数,也可以是类。类装饰器主要依赖于 call 方法,当一个类的实例被当作函数调用时,call 方法就会被执行。

python">class CountCalls:def __init__(self, func):self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs):self.num_calls += 1print(f"调用 {self.func.__name__} {self.num_calls} 次")return self.func(*args, **kwargs)@CountCalls
def say_hello():print("Hello!")say_hello()
say_hello()

2、保留原函数的元数据
使用装饰器时,一个常见的问题是被装饰的函数其实是被替换成了一个新的函数(即 wrapper)。这可能会导致原函数的元数据丢失,比如函数的名称和文档字符串。为了解决这个问题,Python 的 functools 模块提供了一个 wraps 装饰器
使用 functools.wraps 装饰器来保留被装饰函数的元数据:

python">from functools import wrapsdef my_decorator(func):@wraps(func)def wrapper(*args, **kwargs):"""Wrapper function"""print("Something is happening before the function is called.")return func(*args, **kwargs)return wrapper@my_decorator
def say_whee():"""Say whee!"""print("Whee!")print(say_whee.__name__)  # 输出 'say_whee'
print(say_whee.__doc__)   # 输出 'Say whee!'

三、装饰器的常见应用
日志记录、性能测量、访问控制和认证、缓存、错误处理和重试逻辑

四、注意事项
1、装饰器在函数定义时就会执行,而不是在函数调用时。
2、多个装饰器可以堆叠使用,执行顺序是从下到上。
当多个装饰器应用到一个函数上时,它们的执行顺序是从下到上的:

python">@decorator1
@decorator2
def func():pass

这等同于:

python">func = decorator1(decorator2(func))

3、装饰器可能会影响函数的性能,特别是在频繁调用的情况下。
4、使用 functools.wraps 可以保留被装饰函数的元数据。


http://www.ppmy.cn/news/1475335.html

相关文章

中介者模式(大话设计模式)C/C++版本

中介者模式 C // 中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示得相互引用&#xff0c;从而使得其耦合松散&#xff0c;而且可以独立地改变他们之间得交互#include <iostream> #include <string>using namespace std;#d…

需求实现:字数限制500字

摘要&#xff1a; 在浩瀚的技术实现海洋中&#xff0c;每一个需求都如同一块磁石&#xff0c;吸引着多样化的解决策略与技术手段的汇聚。然而&#xff0c;无论选择多么丰富&#xff0c;核心始终在于对业务逻辑的深刻理解&#xff0c;以及为当前特定场景量身定制的最佳实践。本…

使用YOLO5进行模型训练机器学习【教程篇】

准备工作 YOLOv5 是目前非常流行的目标检测模型,广泛应用于各种计算机视觉任务,可以检测到图片中的具体目标。 我们借助开源的模型训练框架,省去了自己写算法的步骤,有技术的伙伴可以深入了解并自己写算法训练。 电脑要求: GPU ,内存 >12G python > =3.8 windows o…

抗量子密码算法:保障未来信息安全的新盾牌

随着量子计算的迅猛发展&#xff0c;传统加密算法正面临着前所未有的挑战。量子计算机利用量子比特的特殊性质&#xff0c;能在极短时间内破解目前广泛使用的公钥加密体系&#xff0c;如RSA、ECC等。这使得我国及全球的信息安全体系遭受严重威胁。为了应对这一挑战&#xff0c;…

STM32智能门禁系统教程

目录 引言环境准备智能门禁系统基础代码实现&#xff1a;实现智能门禁系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;门禁管理与优化问题解决方案与优化收尾与总结 1. 引言 智能门禁系统通过STM32嵌入…

5G与未来通信技术

随着科技的迅猛发展&#xff0c;通信技术也在不断演进。5G技术作为第五代移动通信技术&#xff0c;已成为现代通信技术的一个重要里程碑。本文将详细介绍5G及其对未来通信技术的影响&#xff0c;重点探讨超高速互联网和边缘网络的应用。 一、超高速互联网 1. 低延迟 5G技术最显…

富格林:正确击破暗箱稳健出金

富格林悉知&#xff0c;现在喜欢投资的人都在不断增加&#xff0c;在享受贵金属投资较高出金回报的同时&#xff0c;也该做好遭遇暗箱亏损情况的预防措施。对于新手投资者群体来说&#xff0c;如何客观地认识造成亏损的原因和暗箱&#xff0c;也是贵金属投资道路上必须克服的一…

GPT-4o在Excel的应用

引言 随着人工智能技术的不断进步&#xff0c;GPT-4o已成为许多领域中的重要工具。特别是在数据处理和分析方面&#xff0c;GPT-4o的强大功能可以大大提升工作效率&#xff0c;解放用户从繁琐的公式和手动操作中。本文将详细介绍如何利用GPT-4o在Excel中完成常见但复杂的任务&…

性能监控的革命:Eureka引领分布式服务监控新纪元

性能监控的革命&#xff1a;Eureka引领分布式服务监控新纪元 引言 在微服务架构中&#xff0c;服务的分布式性能监控对于维护系统健康和优化用户体验至关重要。Eureka作为Netflix开源的服务发现框架&#xff0c;为服务的注册与发现提供了强大支持&#xff0c;而结合其他工具&…

【RNN练习】天气预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、环境及数据准备 1. 我的环境 语言环境&#xff1a;Python3.11.9编译器&#xff1a;Jupyter notebook深度学习框架&#xff1a;TensorFlow 2.15.0 2. 导…

【Django+Vue3项目实战】构建高效线上教育平台之首页模块

文章目录 前言一、导航功能实现a.效果图&#xff1a;b.后端代码c.前端代码 二、轮播图功能实现a.效果图b.后端代码c.前端代码 三、标签栏功能实现a.效果图b.后端代码c.前端代码 四、侧边栏功能实现1.整体效果图2.侧边栏功能实现a.效果图b.后端代码c.前端代码 3.侧边栏展示分类及…

防火墙NAT、智能选路综合实验

一、实验拓扑 二、实验要求 1&#xff0c;办公区设备可以通过电信链路和移动链路上网(多对多的NAT&#xff0c;并且需要保留一个公网IP不能用来转换) 2&#xff0c;分公司设备可以通过总公司的移动链路和电信链路访问到Dmz区的http服务器 3&#xff0c;多出口环境基于带宽比例…

音视频封装demo:使用libmp4v2将h264视频数据和aac语音数据封装(mux)成mp4文件

1、README 前言 本demo是使用的mp4v2来将h264、aac封装成mp4文件的&#xff0c;目前demo提供的.a静态库文件是在x86_64架构的Ubuntu16.04编译得到的&#xff0c;如果想在其他环境下测试demo&#xff0c;可以自行编译mp4v2并替换相应的库文件&#xff08;libmp4v2.a&#xff0…

场外期权有交割日吗?场外期权应该怎么交割?

今天带你了解场外期权有交割日吗&#xff1f;场外期权应该怎么交割&#xff1f;场外个股期权是一种非标准化的金融衍生品&#xff0c;它允许投资者在未来某一特定日期以特定价格买入或卖出某一特定股票。 交割日就是买卖双方进行交割的日期,期权合约具有到期日,到期日的后一天…

大众点评商家电话采集软件分享 解析爬虫工具

爬虫工具是一种自动化程序&#xff0c;可用于从网页中提取和分析数据。在本文中&#xff0c;我们将使用Python编写一个大众点评商家电话采集爬虫工具&#xff0c;帮助我们快速获取商家的电话号码。 步骤&#xff1a; 安装必要的库&#xff1a;我们将使用Requests和Beautiful …

hackmyvm--Decode

环境 靶机&#xff1a;ip未知 攻击机kali&#xff1a;192.168.233.128 192.168.56.101 主机探测 锁定靶机ip为108 端口扫描 nmap -p- -T4 -A 192.168.56.108 常规套路80和22 web打点 dirsearch -u http://192.168.56.108/ 访问robots,txt文件 访问/decode 发现其自动添加了/,怀…

Effective C++笔记之二十一:One Definition Rule(ODR)

ODR细节有点复杂&#xff0c;跨越各种情况。基本内容如下&#xff1a; ●普通&#xff08;非模板&#xff09;的noninline函数和成员函数、noninline全局变量、静态数据成员在整个程序中都应当只定义一次。 ●class类型&#xff08;包括structs和unions&#xff09;、模板&…

Python 读取和写入文本文件(txt)、Excel 文件和 JSON 文件的方法

Python 读取和写入文本文件&#xff08;txt&#xff09;、Excel 文件和 JSON 文件的基本方法 读取/写入 txt 文件基本读取txt读取 txt 文件写入 txt 文件按行读取复杂数据处理大txt文本文件&#xff08;逐行读取以节省内存&#xff09; 读取/写入 Excel 文件基本读取读取 Excel…

论文辅导 | 基于模态分解的Transformer-GRU联合电池健康状态估计

辅导文章 模型描述 提出一种基于变分模态分解(variational mode decomposition&#xff0c;VMD)与粒子群优化(particle swarm optimization&#xff0c;PSO)的变换神经网络(Transformer)和门控循环单元(gate recurrent unit&#xff0c;GRU)的联合方法。首先将锂电池容量信息通…

Android.mk中LOCAL_SDK_VERSION的作用是什么?

在Android的NDK&#xff08;Native Development Kit&#xff09;中&#xff0c;Android.mk文件是用于指定如何构建原生&#xff08;C/C&#xff09;代码的一个Makefile脚本。然而&#xff0c;关于LOCAL_SDK_VERSION这个变量&#xff0c;实际上在标准的Android NDK构建系统中并不…