深入了解python装饰器(decorator)

什么是装饰器?

装饰器是 Python 中的一种高级功能,它允许你在不修改现有代码的情况下为函数或方法添加新的行为。装饰器本质上是一个接受函数并返回另一个函数的高阶函数。这使得它们非常适合用于横切关注点(如日志记录、权限检查、性能计时等),因为它们可以在不改变目标函数代码的前提下扩展其功能。

装饰器的基本用法

一个简单的装饰器如下所示:为say_hello函数添加打印执行前和执行后的提示信息

def my_decorator(func):def wrapper():print("Something is happening before the function is called.")func()print("Something is happening after the function is called.")return wrapper@my_decorator
def say_hello():print("Hello!")say_hello()

输出:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

在这个例子中,my_decorator 是一个装饰器函数,它接收一个函数 func 作为参数,并返回一个新的函数 wrapper@my_decorator 语法相当于 say_hello = my_decorator(say_hello)

带参数的装饰器

装饰器本身也可以接受参数。为此,我们需要再多包一层:
以下repeat装饰器让别装饰的函数执行指定次数

def repeat(num_times):def decorator_repeat(func):def wrapper(*args, **kwargs):for _ in range(num_times):func(*args, **kwargs)return wrapperreturn decorator_repeat@repeat(num_times=3)
def greet(name):print(f"Hello, {name}!")greet("Alice")

输出:

Hello, Alice!
Hello, Alice!
Hello, Alice!

在这个例子中,repeat 是一个接受参数的装饰器工厂,它返回一个实际的装饰器 decorator_repeat

装饰器与函数签名

为了让装饰器不改变被装饰函数的签名,可以使用 functools.wraps 来保留原函数的元数据:

import functoolsdef my_decorator(func):@functools.wraps(func)def wrapper(*args, **kwargs):print("Before calling the function")result = func(*args, **kwargs)print("After calling the function")return resultreturn wrapper@my_decorator
def say_hello(name):print(f"Hello, {name}")say_hello("Alice")
print(say_hello.__name__)

输出:

Before calling the function
Hello, Alice
After calling the function
say_hello

装饰器的实际应用

1. 日志记录

打印函数的接受的参数与返回值

def log_decorator(func):@functools.wraps(func)def wrapper(*args, **kwargs):print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")result = func(*args, **kwargs)print(f"{func.__name__} returned {result}")return resultreturn wrapper@log_decorator
def add(a, b):return a + badd(2, 3)

输出:

Calling add with args: (2, 3), kwargs: {}
add returned 5

2. 权限检查

def requires_permission(permission):def decorator(func):@functools.wraps(func)def wrapper(*args, **kwargs):if not user_has_permission(permission):raise PermissionError(f"User lacks {permission} permission")return func(*args, **kwargs)return wrapperreturn decorator@requires_permission("admin")
def delete_user(user_id):print(f"User {user_id} deleted")# Assuming user_has_permission("admin") returns False
delete_user(123)  # Raises PermissionError

3. 缓存

def cache(func):cached_results = {}@functools.wraps(func)def wrapper(*args):if args in cached_results:return cached_results[args]result = func(*args)cached_results[args] = resultreturn resultreturn wrapper@cache
def fibonacci(n):if n in (0, 1):return nreturn fibonacci(n - 1) + fibonacci(n - 2)print(fibonacci(10))

类装饰器

类也可以用作装饰器,实现更复杂的逻辑或状态管理:
使用类装饰器,记录函数被调用的次数

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

输出:

Call 1 of say_hello
Hello!
Call 2 of say_hello
Hello!

总结

装饰器是 Python 中强大的工具,能够在不修改原函数代码的前提下添加额外的功能。通过理解装饰器的原理和使用方法,你可以编写更加灵活和可维护的代码。无论是日志记录、权限检查、性能计时还是缓存,装饰器都提供了一种优雅的解决方案。

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

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

相关文章

有什么值得推荐的文件外发权限管理软件?

你的身边有这种事情发生吗? 一些工作人员在传达文件、部署工作时,为贪图方便,直接将涉密文件、涉密工作通过微信群传达部署,造成了大量泄密案件发生。 有些责任人员为了工作方便,对涉密文件进行拍照,通过…

jar包运行脚本

start: # 启动项目 #!/bin/bash nohup java -jar audit-2.1.0.jar > app.log 2>&1 & quit: # 关闭程序 #!/bin/bash PID$(pgrep -f audit-2.1.0.jar) # 根据应用程序名称查找进程ID kill -9 $PID # 结束进程使用 sh命令运行

LIMS系统如何应用在锂电行业中呢

LIMS实验室管理系统在锂电行业的应用主要体现在实验室管理、质量控制、生产流程优化以及数据分析和决策支持等方面。 以下是LIMS系统在锂电行业中的具体应用。 一、实验室管理 样品管理 LIMS系统可以追踪样品的整个生命周期,包括样品的接收、登记、分配、检测进度、…

Python运算符重载,代码秒变高大上!

目录 1、运算符重载基础介绍 🧮 1.1 什么是运算符重载 1.2 为何使用运算符重载 1.3 Python中的特殊方法魔法 示例:重载加法运算符 2、实战:重载加法运算符 + 🧩 2.1 自定义类与__add__() 2.2 应用案例:复数加法 2.3 深入理解__add__方法 3、重载其他运算符示例…

Cytoscape之操作界面介绍

Cytoscape 简介 Cytoscape是一个专注于开源网络可视化和分析的软件。软件的核心部分提供了网络显示、布局、查询等方面的基本功能。软件的核心可以通过插件架构进行扩展,这样就能快速地开发出新的功能。 Cytoscape 源自系统生物学,用于将生物分子交互网…

Linux和Windows(VS 2019)下安装使用Log4cpp日志库

目录 一、Log4cpp简介 二、Windows下的Log4cpp的安装 1、下载网址 2、解决方案 三、Vistual Studio中使用第三方库 1、拷贝对应下图路径下的include文件进入你的项目目录下面去,并将之前编译好的库文件也放在对应项目目录下面去。 2、打开你的项目&#xff0…

nacos 配置修改.代码实时刷新

再类上用 RefreshScope 更新Value(“${uniqlo.privacy.url:https://wsurl.cc/yourls-api.php}”) private String shortLinkGenerateUrl;的数据可以实时更新 2.再配置类上次用 ConfigurationProperties(prefix “test.privacy”) 和nacos的配置一直 Data Component Configu…

华为云EI生态

1、人工智能技术趋势 2、华为AI发展思路 3、华为云EI:让企业更智能 4、华为云服务全景图 5、基础平台类服务 6、MLS:解决特性到模型应用的完整过程 7.DLS 8.GES超大规模一体化图分析与查询 9、EI视觉认知 10、EI语音语义 11、OCR:提供高精度光学文字自动…

在Apache Flink中,Java UDF(用户自定义函数)的使用涉及几个关键步骤

在Apache Flink中,Java UDF(用户自定义函数)的使用涉及几个关键步骤:创建UDF类、注册UDF、以及在Flink作业中使用UDF。以下是一些具体的使用案例: ### 1. 创建项目和配置POM 首先,创建一个Maven项目&…

Kubernetes Pod 健康问题:CrashLoopBackoff

搭建 Prometheus 的过程中,alertmanager-main 的 Status状态为CrashLoopBackoff. 我的alertmanager-main svc下有三个alertmanager-main-0 alertmanager-main-1 alertmanager-main-2 1.检查状态 kubectl describe pod alertmanager-main-0 -n monitoring输出的关键…

C++初学者指南第一步---9.函数

C初学者指南第一步—9.函数 文章目录 C初学者指南第一步---9.函数1.输入和输出1.1第一个例子1.2返回类型1.3函数参数常量参数默认值参数 1.4函数重载 2.函数执行2.1递归2.2 声明和定义 3.函数设计3.1约定3.2 特性[[nodiscard]] (C17)3.3 不抛出异常保证&…

项目实战—springboot整合微信、支付宝NATIVE扫码支付

目录 微信支付申请微信支付添加依赖WechatConstant配置httpClient生成支付二维码支付成功回调订单退款 支付宝支付申请支付宝支付添加依赖配置AlipayClient生成支付二维码支付成功回调订单退款 可能出现的问题 微信支付 申请微信支付 接入微信支付前需要再微信开放平台、公众…

【Python驯化-01】python中set去重数据每次结果不一致问题解决

【Python驯化-01】python中set去重数据每次结果不一致问题解决 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 免费获取相关内容文档关注…

信息安全系列课程之网络空间测绘与态势感知技术揭秘(一)

今天,我们来讲一下网络安全! 本文章仅提供学习,切勿将其用于不法手段! 目前,在信息安全攻防领域,主要分为了两个技术发展方向,分别为渗透测试(红队技术) 和 安全运维&a…

考研计组chap2数据的表示和运算

3一、进位计数制 1.r进制 第i位表示r进制的权为i 2.进制转换 (1)r->10 对应位置数*权值 (2)2 -> 16 or 8 每三位2进制数可表示1位16进制 每四位2进制数可表示1位16进制 so 分开之后转为16进制即可 eg:1…

江苏省SAP代理商之选:无锡哲讯为企业信息化管理开启新篇章

江苏省,作为中国东部沿海的经济重镇,拥有众多行业领先企业。随着数字化转型的浪潮,SAP代理商在这片热土上扮演着至关重要的角色。无锡哲讯智能科技有限公司(iP-Solutions),作为SAP在华东地区的金牌合作伙伴…

基于51单片机恒温箱设计

基于51单片机恒温箱设计 (程序+原理图+设计报告) 功能介绍 具体功能: 本设计由STC89C52单片机电路数字温度传感器DS18B20电路按键电路蜂鸣器报警电路继电器控制电路LCD1602液晶显示电路电源电路组成。 1.LCD1602液…

Spring源码中是如何使用设计模式六大原则的

设计模式的六大原则,通常指的是SOLID原则,它们是面向对象设计中用于提高代码可维护性、灵活性和可扩展性的五个指导原则,学习六大原则,可以让你的代码变得高级而优雅,今天的内容 V 哥结合 Spring源码中如何运用六大原则…

偏微分方程算法之抛物型方程差分格式编程示例四(Richardson外推)

目录 一、研究问题 二、C++代码 三、结果分析 一、研究问题 已知其精确解为。分别取以下三种步长: ①

流程引擎框架

SpiffWorkflow python 流程引擎框架哪个好 Camunda 核心表介绍 https://zhuanlan.zhihu.com/p/645786758 camunda流程引擎基本使用(笔记) https://blog.csdn.net/weixin_46949627/article/details/129255647 python连接FastDfs服务封装类 https://blog.c…