Python装饰器教学

Python装饰器教学

一、装饰器简介

在Python中,装饰器是一种高级语法特性,允许你修改或增强函数、方法或类的行为,而无需修改其源代码。装饰器本质上是一个接受函数作为参数的函数,并返回一个新的函数对象。

二、装饰器的基本用法

下面是一个简单的装饰器示例:

def my_decorator(func):def wrapper():print("Before function call")func()print("After function call")return wrapper@my_decorator
def say_hello():print("Hello!")say_hello()

输出:

Before function call
Hello!
After function call

在这个例子中,my_decorator 是一个装饰器函数,它接受一个函数 func 作为参数,并返回一个新的函数 wrapperwrapper 函数在调用原始函数 func 之前和之后分别打印一些内容。

通过使用 @my_decorator 语法,我们可以将装饰器应用到任何函数上,如 say_hello 函数。这实际上是将 say_hello 函数作为参数传递给 my_decorator 函数,并将返回的新函数对象重新赋值给 say_hello

三、带参数的装饰器

如果原始函数需要接受参数,我们可以在 wrapper 函数中添加相应的参数,如下所示:

def my_decorator(func):def wrapper(name):print(f"Before calling {func.__name__}")func(name)print(f"After calling {func.__name__}")return wrapper@my_decorator
def greet(name):print(f"Hello, {name}!")greet("Alice")

输出:

Before calling greet
Hello, Alice!
After calling greet

在这个例子中,greet 函数接受一个参数 name,并通过装饰器 my_decorator 增强了其行为。注意,在 wrapper 函数中,我们使用 func.__name__ 来获取原始函数的名称。

四、带参数的装饰器工厂

有时,我们可能希望装饰器本身能够接受参数。这可以通过创建一个返回装饰器的函数来实现,如下所示:

def my_decorator_factory(message):def my_decorator(func):def wrapper(name):print(f"{message} Before calling {func.__name__}")func(name)print(f"{message} After calling {func.__name__}")return wrapperreturn my_decorator@my_decorator_factory("This is a custom message: ")
def greet(name):print(f"Hello, {name}!")greet("Bob")

输出:

This is a custom message: Before calling greet
Hello, Bob!
This is a custom message: After calling greet

在这个例子中,my_decorator_factory 是一个返回装饰器的函数。它接受一个参数 message,并返回一个装饰器函数 my_decorator。这样,我们就可以通过传递不同的参数来创建具有不同行为的装饰器。

五、装饰器的应用场景

装饰器在Python编程中有许多应用场景,例如:

  1. 日志记录:记录函数调用的时间、参数和返回值等信息。
  2. 权限校验:在函数调用之前检查用户权限。
  3. 缓存实现:缓存函数调用的结果,避免重复计算。
  4. 性能统计:测量函数执行的时间并打印性能报告。
  5. 事务处理:确保数据库操作的原子性、一致性和隔离性。
  6. 测试与调试:在开发过程中添加额外的调试信息或测试逻辑。

六、日志记录示例

日志记录是装饰器的一个非常实用的应用场景。下面是一个使用装饰器来实现日志记录的示例:

import logging
from functools import wraps# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')# 定义一个日志装饰器
def log_decorator(func):@wraps(func)  # 使用 functools.wraps 来保留原始函数的元信息(如函数名、文档字符串等)def wrapper(*args, **kwargs):# 在函数调用前记录日志logging.info(f"Calling function {func.__name__} with args {args} and kwargs {kwargs}")# 调用原始函数并获取结果result = func(*args, **kwargs)# 在函数调用后记录日志logging.info(f"Function {func.__name__} returned {result}")# 返回函数结果return resultreturn wrapper# 使用装饰器来增强函数
@log_decorator
def add_numbers(a, b):"""Adds two numbers and returns the result."""return a + b# 调用增强后的函数
result = add_numbers(5, 3)
print(result)

在这个例子中,我们首先导入了 logging 模块和 functools.wraps 装饰器。logging 模块用于记录日志,而 wraps 装饰器用于保留原始函数的元信息,这样在日志中就可以正确地显示函数名。

我们定义了一个名为 log_decorator 的装饰器,它接受一个函数作为参数,并返回一个新的函数 wrapper。在 wrapper 函数内部,我们在调用原始函数前后分别记录了日志。

然后,我们使用 @log_decorator 语法将装饰器应用到 add_numbers 函数上。这样,每当我们调用 add_numbers 函数时,就会自动记录相应的日志。

运行这段代码,你将看到类似以下的输出:

2023-04-25 10:00:00,000 - INFO - Calling function add_numbers with args (5, 3) and kwargs {}
2023-04-25 10:00:00,001 - INFO - Function add_numbers returned 8
8

这里的日志输出显示了函数调用前后的信息,包括函数名、参数和返回值。这对于调试和监控程序的运行非常有用。

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

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

相关文章

详解:写作和赚钱的 4 个关系!看完你一定会忍不住想开始写!

飞书文档的加密很强,也没有和自家的豆包大模型融合,所以只能通过其他方式获取文档的内容。 (1)将飞书文档转换为PDF,要用到浏览器插件: GoFullPage - Full Page Screen Capture - Microsoft Edge Addons …

Golang 环境变量配置 mockgen安装(macOS系统)

1、将 $GOPATH/bin 添加到环境变量中 查看当前的 GOPATH 地址: go env GOPATH 将 GOPATH/bin 地址添加到系统环境变量里: 打开 zsh 终端文件 sudo vim ~/.zshrc 添加此路径到 zshrc 文件最后一行 export PATH$PATH:${GOPATH}/bin 2、安装 mockge…

[生活感悟]不生孩子有什么坏处?

不生孩子有什么坏处? 对于没有孩子的成年人来说,时间的变化是不同的。 I’ve noticed that I have a very different sense of time passing since I’m not attached to the school calendar. I tend to not notice it passing as much. And then abru…

RT-Thread动态内存扩展,使用多块不连续的RAM作为动态内存

开发环境 MCU:STM32F429VET6(1M Flash,192K64K共256K SRAM) 编译环境:MDK5.38 实时系统:RT-Thread标准版 目的 这颗MCU的SRAM默认是使用192K,即从地址0x20000000开始,最大0x30000…

VS code配置Markdown以及预览

1.安装 Visual Studio Code: 如果尚未安装Visual Studio Code,请先下载并安装它。您可以从官方网站(https://code.visualstudio.com/)下载适用于您的操作系统的版本。 2安装扩展 Visual Studio Code的强大之处在于其扩展生态系…

python生成requirement.txt

pipreqs第三方库(推荐) 使用 pipreqs 可以自动检索到当前项目下的所有组件及其版本,并生成 requirements.txt 文件,极大方便了项目迁移和部署的包管理。相比直接用pip freeze 命令,能直接隔离其它项目的包生成。 使用…

第九届蓝桥杯大赛个人赛省赛(软件类)真题C 语言 A 组-分数

solution1 直观上的分数处理 #include <iostream> using namespace std; int main() {printf("1048575/524288");return 0; }#include<stdio.h> #include<math.h> typedef long long ll; struct fraction{ll up, down; }; ll gcd(ll a, ll b){if…

2024中国闪存市场观察:AI助推闪存全面起势?

过去两年&#xff0c;闪存市场一直处于低迷状态&#xff0c;但去年第四季度闪存颗粒资源的上涨&#xff0c;导致闪存产品价格一路上扬&#xff0c;市场遂发生反转。 2024年&#xff0c;中国闪存市场会彻底走向复苏&#xff0c;还是急转直下&#xff1f;中国AI热潮&#xff0c;…

MATLAB 自定义生成平面点云(可指定方向,添加噪声)(48)

MATLAB 自定义生成平面点云(可指定方向,添加噪声)(48) 一、算法介绍二、算法步骤三、算法实现1.代码2.效果一、算法介绍 通过这里的平面生成方法,可以生成模拟平面的点云数据,并可以人为设置平面方向,平面大小,并添加噪声来探索不同类型的平面数据。这种方法可以用于…

【大全】常用加解密算性能、安全对比

常用算法 1、古典加密算法 古典密码&#xff08;classical cryptography&#xff09;编码方式归根结底主要就是置换和代换. 置换&#xff1a;已知明文字母集S{a,b}&#xff0c;置换后的密码可以是S’{b,a}&#xff0c;即将明文字符位置发生变化后形成的密码就是置换密码. 代换&…

JavaScript高架高级(四)---这可能是你看过的最完整的this指向

前言 简单阐述 前端的初学者在学习Javascript中this指向的时候经常都会一头雾水&#xff0c;尤其是在ES6箭头函数出现之前。 this指向之所以容易让人头疼&#xff0c;原因在于 this 是在代码执行时根据环境和情况不同才决定绑定为什么值。 所以本篇文章主要是介绍和总结了各…

Openstack(T) 部署Ceilometer服务 ---mongo命令error

执行如下命令 # mongo --host controller --eval db db.getSiblingDB("ceilometer"); db.addUser({user: "ceilometer", pwd: "admin123", roles: [ "readWrite", "dbAdmin" ]}) 出现错误 1.安装mongo ①vi /etc/yum.r…

数据结构进阶篇 之 【二叉树】详细概念讲解(带你认识何为二叉树及其性质)

有朋自远方来&#xff0c;必先苦其心志&#xff0c;劳其筋骨&#xff0c;饿其体肤&#xff0c;空乏其身&#xff0c;鞭数十&#xff0c;驱之别院 一、二叉树 1、二叉树的概念 1.1 二叉树中组分构成名词概念 1.2 二叉树的结构概念 1.3 特殊的二叉树 2、二叉树的存储结构 …

全面:vue.config.js 的完整配置

vue.config.js是Vue项目的配置文件&#xff0c;用于配置项目的构建、打包和开发环境等。 在Vue CLI 3.0之后&#xff0c;项目的配置文件从原来的build和config目录下的多个配置文件&#xff0c;合并成了一个vue.config.js文件。这个文件可以放在项目的根目录下&#xff0c;用于…

向赵丽颖学习大女主式的生活方式!

最近&#xff0c;随着电视剧《与凤行》的热播&#xff0c;赵丽颖再次以其精湛的演技和不变的专业状态回到了大众视野。从《楚乔传》的坚韧女将到《知否知否应是绿肥红瘦》中的睿智女性&#xff0c;赵丽颖的每一次转变都让人眼前一亮。尽管在这几年中&#xff0c;她也经历了许多…

AI入侵游戏业:是颠覆者还是创新助手?揭秘未来游戏新趋势!

在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经成为各行各业的关注焦点。而在娱乐产业中&#xff0c;AI技术的引入也让人们对电子游戏的未来发展产生了无限遐想。那么&#xff0c;AI究竟会给电子游戏行业带来怎样的变革&#xff1f;它会成为行业的颠…

机器学习 - save和load训练好的模型

如果已经训练好了一个模型&#xff0c;你就可以save和load这模型。 For saving and loading models in PyTorch, there are three main methods you should be aware of. PyTorch methodWhat does it do?torch.saveSaves a serialized object to disk using Python’s pickl…

AI大模型学习的伦理与社会影响

AI大模型学习 随着人工智能技术的快速发展&#xff0c;AI大模型学习成为当前热门研究领域之一。AI大模型学习是指基于大规模数据集和深度学习模型进行训练&#xff0c;以实现更高的准确性和复杂性。这些大模型已经在几乎所有领域都取得了显著的成就&#xff0c;包括自然语言处…

通讯录管理系统实现(C++版本)

1.菜单栏的设置 &#xff08;1&#xff09;我么自定义了一个showmenu函数&#xff0c;用来打印输出我们的菜单栏&#xff1b; &#xff08;2&#xff09;菜单栏里面设置一些我们的通讯录里面需要用到的功能&#xff0c;例如增加联系人&#xff0c;删除联系人等等 2.退出功能…

ocrclass.h:117:18: error: field ‘end_time‘ has incomplete type ‘timeval‘

Alpine Linux v3.5上安装 tesseract-4.1.1 报错&#xff1a; 缺少timeval函数 ocrclass.h:117:18: error: field end_time has incomplete type timeval Current Behavior: In file included from control.cpp:37:0: ../../src/ccutil/ocrclass.h:117:18: error: field end…