Python常见装饰器使用(实用向)
目录
- 1.`@staticmethod`
- 2.`@classmethod`
- 3、`@classmethod` 与`@staticmethod`比较
- 4. `@property`
- 5.`@abstractmethod`
- 6.`@wraps`
- 7.`@lru_cache`
- 8.`@timeout`
- 9.`@retry`
@staticmethod:将一个方法转换为静态方法,可以在不创建类实例的情况下调用。@classmethod:将一个方法转换为类方法,可以在不创建类实例的情况下调用,并且可以访问类的属性和方法。@property:将一个方法转换为属性,可以像访问属性一样访问方法,而不需要使用括号调用。@abstractmethod:定义一个抽象方法,子类必须实现该方法才能被实例化。@wraps:将一个函数的元信息(如函数名、文档字符串、参数列表等)复制到另一个函数中,可以避免装饰器对函数元信息的影响。@lru_cache:使用 LRU 算法实现的缓存装饰器,可以缓存函数的计算结果,避免重复计算。@timeout:设置函数的最大执行时间,如果函数执行时间超过设定的时间,就会抛出TimeoutError异常。@retry:在函数执行失败时自动重试,可以设置重试次数、重试间隔等参数。
这些装饰器都是 Python 中常用的装饰器,可以帮助我们简化代码、提高效率、增强程序的可读性和可维护性。
1.@staticmethod
class MyClass:@staticmethoddef my_static_method(x, y):return x + y# 不需要创建类实例,直接调用静态方法
result = MyClass.my_static_method(1, 2)
print(result) # 输出 3
2.@classmethod
class MyClass:class_var = 0@classmethoddef my_class_method(cls, x):cls.class_var += xreturn cls.class_var# 不需要创建类实例,直接调用类方法
result1 = MyClass.my_class_method(1)
result2 = MyClass.my_class_method(2)
print(result1, result2) # 输出 1 3
3、@classmethod 与@staticmethod比较
classmethod 和 staticmethod 都是 Python 中的装饰器,用于定义类方法和静态方法。虽然它们都可以在类中定义方法,通过类名直接调用,而不需要创建类的实例,但是它们有一些不同之处。
不同点:
classmethod的第一个参数是类本身,通常命名为cls,而staticmethod没有特殊的参数。classmethod可以访问和修改类的属性和方法,而staticmethod只能访问类的属性和方法,不能修改它们。classmethod可以被子类继承和重写,而staticmethod不会被继承和重写。
以下是一个简单的示例代码,演示了如何使用 classmethod 和 staticmethod:
class MyClass:class_variable = 0def __init__(self, instance_variable):self.instance_variable = instance_variable@classmethoddef class_method(cls):cls.class_variable += 1print("Class variable:", cls.class_variable)@staticmethoddef static_method():print("Static method")# 调用类方法
MyClass.class_method() # 输出 Class variable: 1# 创建类实例
obj = MyClass(10)# 调用静态方法
obj.static_method() # 输出 Static method# 调用类方法
obj.class_method() # 输出 Class variable: 2
4. @property
将一个方法转换为属性,可以像访问属性一样访问方法,而不需要使用括号调用。
我们使用 @property 装饰器定义了一个 getter 方法 x,用于获取私有属性 _x 的值。我们使用 @x.setter 装饰器定义了一个 setter 方法 x,用于设置私有属性 _x 的值。
class MyClass:def __init__(self, x):self._x = x@propertydef x(self):return self._x@x.setterdef x(self, value):self._x = value# 访问属性 x,实际上调用的是方法 x()
obj = MyClass(1)
print(obj.x) # 输出 1# 修改属性 x,实际上调用的是方法 x(value)
obj.x = 2
print(obj.x) # 输出 2
5.@abstractmethod
abstractmethod 是 Python 中的一个装饰器,用于定义抽象方法。抽象方法是一种没有实现的方法,它只是一个接口,需要在子类中实现。抽象方法通常用于定义一个类的接口,而不是具体的实现。
使用 abstractmethod 装饰器可以让我们在抽象类中定义抽象方法,强制要求子类实现这些方法。如果子类没有实现抽象方法,那么在实例化子类时会抛出 TypeError 异常。
以下是一个简单的示例代码,演示了如何使用 abstractmethod 装饰器定义抽象方法:
from abc import ABC, abstractmethodclass Shape(ABC):@abstractmethoddef area(self):passclass Rectangle(Shape):def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightclass Circle(Shape):def __init__(self, radius):self.radius = radiusdef area(self):return 3.14 * self.radius ** 2# 创建 Rectangle 和 Circle 对象,并调用 area() 方法
rect = Rectangle(10, 20)
print("Rectangle area:", rect.area())circle = Circle(5)
print("Circle area:", circle.area())# 创建 Shape 对象,会抛出 TypeError 异常
shape = Shape()
# TypeError: Can't instantiate abstract class Shape with abstract methods area
6.@wraps
wraps 是 Python 中的一个装饰器,用于修饰其他装饰器,它可以帮助我们保留被修饰函数的元信息,例如函数名、文档字符串、参数列表等。如果我们不使用 wraps 装饰器,那么被修饰函数的元信息可能会丢失或被修改,导致代码可读性和可维护性下降。
使用 wraps 装饰器的主要用途是在编写装饰器时,保留被修饰函数的元信息。例如,如果我们编写一个装饰器,用于记录函数的执行时间,那么使用 wraps 装饰器可以保留被修饰函数的函数名、文档字符串、参数列表等信息,使得调试和维护代码更加方便。
以下是一个简单的示例代码,演示了如何使用 wraps 装饰器保留被修饰函数的元信息:
from functools import wraps
import timedef timer(func):@wraps(func)def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()print(f"{func.__name__} took {end_time - start_time:.2f} seconds")return resultreturn wrapper@timer
def my_func():"""This is a docstring"""print("Hello, world!")my_func()
print("Function name:", my_func.__name__)
print("Docstring:", my_func.__doc__)
# (env) [hanhandi@VM-33-162-centos ~/hanhan_PythonScripts/装饰器使用]$ python other.py
# Hello, world!
# my_func took 0.00 seconds
# Function name: my_func
# Docstring: This is a docstring
在上面的代码中,我们定义了一个名为 timer 的装饰器,用于记录函数的执行时间。我们使用 @wraps 装饰器修饰了内部的 wrapper 函数,保留了被修饰函数的元信息。然后,我们定义了一个名为 my_func 的函数,并使用 @timer 装饰器修饰它。最后,我们调用了 my_func() 函数,并输出了它的执行时间、函数名和文档字符串。
使用 wraps 装饰器可以让我们编写更加健壮和可维护的装饰器,同时也可以提高代码的可读性和可维护性。
7.@lru_cache
这个之前有讲解过,不过之前用的是cachetools:
https://blog.csdn.net/qq_42604176/article/details/130045268?spm=1001.2014.3001.5501
from functools import lru_cache@lru_cache(maxsize=128)
def fibonacci(n):if n < 2:return nreturn fibonacci(n-1) + fibonacci(n-2)# 缓存函数的计算结果,避免重复计算
result = fibonacci(10)
print(result) # 输出 55
8.@timeout
timeout 是 Python 中的一个装饰器,用于设置函数的最大执行时间。如果函数在规定的时间内没有执行完毕,那么装饰器会抛出 TimeoutError 异常,中断函数的执行。
使用 timeout 装饰器的主要用途是在编写需要限制执行时间的函数时,保证函数不会一直执行下去,避免出现死循环或长时间阻塞的情况。例如,如果我们编写一个函数,用于从远程服务器下载文件,那么使用 timeout 装饰器可以设置最大下载时间,避免下载过程中出现网络故障或服务器故障导致程序一直阻塞。
以下是一个简单的示例代码,演示了如何使用 timeout 装饰器设置函数的最大执行时间:
import signalclass TimeoutError(Exception):passdef timeout(seconds):def decorator(func):def handler(signum, frame):raise TimeoutError("Function timed out")def wrapper(*args, **kwargs):signal.signal(signal.SIGALRM, handler)signal.alarm(seconds)result = func(*args, **kwargs)signal.alarm(0)return resultreturn wrapperreturn decorator@timeout(5)
def my_func():import timetime.sleep(10)print("Function finished")try:my_func()
except TimeoutError as e:print("Function timed out:", e)
在上面的代码中,我们定义了一个名为 timeout 的装饰器,用于设置函数的最大执行时间。我们首先定义了一个名为 TimeoutError 的异常类,用于在函数超时时抛出异常。然后,我们定义了一个名为 decorator 的装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapper。在 wrapper 函数中,我们使用 signal 模块设置了一个定时器,当函数执行时间超过规定的时间时,会抛出 TimeoutError 异常。最后,我们使用 @timeout(5) 装饰器修饰了 my_func 函数,设置了最大执行时间为 5 秒。在调用 my_func() 函数时,如果函数执行时间超过 5 秒,会抛出 TimeoutError 异常。
使用 timeout 装饰器可以让我们编写更加健壮和可靠的函数,避免出现死循环或长时间阻塞的情况。同时,它也可以提高代码的可读性和可维护性。
9.@retry
retry 是 Python 中的一个装饰器,用于在函数执行失败时自动重试。如果函数执行失败,装饰器会等待一段时间后再次执行函数,直到函数执行成功或达到最大重试次数为止。
使用 retry 装饰器的主要用途是在编写需要重试的函数时,保证函数能够在失败后自动重试,避免出现因网络故障、服务器故障或其他原因导致函数执行失败的情况。例如,如果我们编写一个函数,用于从远程服务器下载文件,那么使用 retry 装饰器可以设置最大重试次数和重试间隔时间,避免下载过程中出现网络故障或服务器故障导致程序中断。
以下是一个简单的示例代码,演示了如何使用 retry 装饰器设置函数的重试次数和间隔时间:
import timeclass RetryError(Exception):passdef retry(max_retries, wait_time):def decorator(func):def wrapper(*args, **kwargs):for i in range(max_retries):try:result = func(*args, **kwargs)return resultexcept Exception as e:print(f"Function failed: {e}")if i < max_retries - 1:print(f"Retrying in {wait_time} seconds...")time.sleep(wait_time)raise RetryError(f"Function failed after {max_retries} retries")return wrapperreturn decorator@retry(max_retries=3, wait_time=2)
def my_func():import randomif random.random() < 0.8:raise Exception("Random error")else:print("Function succeeded")try:my_func()
except RetryError as e:print("Function failed:", e)# Function failed: Random error
# Retrying in 2 seconds...
# Function failed: Random error
# Retrying in 2 seconds...
# Function failed: Random error
# Function failed: Function failed after 3 retries
在上面的代码中,我们定义了一个名为 retry 的装饰器,用于设置函数的最大重试次数和重试间隔时间。我们首先定义了一个名为 RetryError 的异常类,用于在函数重试次数达到最大值时抛出异常。然后,我们定义了一个名为 decorator 的装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapper。在 wrapper 函数中,我们使用 for 循环和 try/except 语句实现了函数的重试逻辑。如果函数执行失败,会等待一段时间后再次执行函数,直到函数执行成功或达到最大重试次数为止。最后,我们使用 @retry(max_retries=3, wait_time=2) 装饰器修饰了 my_func 函数,设置了最大重试次数为 3 次,重试间隔时间为 2 秒。在调用 my_func() 函数时,如果函数执行失败,会自动重试,直到函数执行成功或达到最大重试次数为止。
使用 retry 装饰器可以让我们编写更加健壮和可靠的函数,避免出现因网络故障、服务器故障或其他原因导致函数执行失败的情况。同时,它也可以提高代码的可读性和可维护性。
相关文章:
Python常见装饰器使用(实用向)
目录1.staticmethod2.classmethod3、classmethod 与staticmethod比较4. property5.abstractmethod6.wraps7.lru_cache8.timeout9.retrystaticmethod:将一个方法转换为静态方法,可以在不创建类实例的情况下调用。classmethod:将一个方法转换为…...
集合详解之(三)单列集合接口Set及具体子类HashSet、TreeSet
文章目录🐒个人主页🏅JavaSE系列专栏📖前言:🎀Set集合接口🎀HashSet实现类🎀TreeSet实现类🪅HashSet类常用方法:🪅TreeSet类常用方法:ὁ…...
力扣刷题笔记22—— 矩阵中的路径(回溯)/pair的学习
矩阵中的路径(回溯)/pair的学习问题分析示例代码pair学习问题 来自力扣: 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按…...
Spring学习1
一、Spring简介 Spring翻译过来就是春天的意思,其实也就是给软件行业带来了春天2002年,首次推出Spring框架的雏形,interface21框架Spring框架就是以interface21框架为基础,经过重新设计,并不断丰富,在2004年…...
Keep再闯IPO,三年亏损16亿,会员留存率跌破70%
“运动科技第一股”来了? 3月28日,线上健身平台的运营方、北京卡路里科技有限公司(下称“Keep”)更新招股书,再次闯关港股IPO。 Keep是一家在线健身平台,主要产品包括在线健身内容、智能健身设备和配套运…...
软件测试分类详解
一图看清软件测试分类 一、按测试技术分(是否查看代码) **1. 黑盒测试**:软件功能是否正常使用【功能的测试】 **2. 白盒测试**:代码逻辑是否正确【结构的测试】 **3. 灰盒测试**:介于两者之间的测试,也…...
网站怎么优化出排名
网站怎么优化出排名,独立站SEO优化应该怎么做?#独立站#推广优化#SEO优化 今天跟大家聊一下独立站的SEO,是指个人或者小型的企业对独立站进行一个优化,以提高他在搜索引擎中的排名和流量,从而吸引更多的这个客户和用户。…...
h5|web页面嵌套iframe传参给cocosCreator
h5|web页面嵌套iframe传参给cocosCreator 目录 一、快速浏览 二、详细实现与项目代码 三、安全性评估——iframe 实现效果: 一、快速浏览 在h5页面中,使用JavaScript获取需要传递的参数,如下: var token ZHESHINIDETOKEN; var phone 11…...
阿里云安全产品Web应用防火墙是什么?有什么作用?
Web应用防火墙是一款网站Web应用安全的防护产品,拦截针对您网站发起的Web通用攻击(如SQL注入、XSS跨站等)或是应用资源消耗型攻击(CC),同时也可以满足您网站从流量管理角度来防御业务风险,例如B…...
【SSM】Spring6(九.代理模式)
文章目录1.代理模式2. 静态代理3. 动态代理3.1 JDK动态代理3.2 CGLIB动态代理1.代理模式 代理模式主要有两种: 静态代理模式 动态代理模式 2. 静态代理 有这样一个业务:订单的生成,修改,查看详情。实现如下 package com.sdnu.…...
【1017. 负二进制转换】
来源:力扣(LeetCode) 描述: 给你一个整数 n ,以二进制字符串的形式返回该整数的 负二进制(base -2)表示。 注意, 除非字符串就是 "0",否则返回的字符串中不…...
C语言实现插入排序与希尔排序
目录 一,插入排序 插入排序C语言实现(升序) 1,将新元素插入到有序序列 2,循环的开始与终止 二,希尔排序 希尔排序C语言实现(升序) 1,单趟: 2&#x…...
第九章-DOM与CSS
style属性 文档中每个元素节点都有一个属性style。style属性包含着元素样式,查询这个属性将返回一个对象而不是一个简单的字符串。样式都存放在这个style对象的属性里。 var element getElementById("example") //查看颜色属性 element.style.color //…...
蓝桥杯真题练习
小蓝在玩一个寻宝游戏, 游戏在一条笔直的道路上进行, 道路被分成了 nn 个方格, 依次编号 1 至 nn, 每个方格上都有一个宝物, 宝物的分值是一个整数 (包括正数、负数和零), 当进入一个方格时即获得方格中宝物的分值。小蓝可 以获得的总分值是他从方格中获得的分值之和。 小蓝开始…...
插入排序的简单理解
详细描述 插入排序的基本思想是:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增 1 的有序表。 在其实现过程中使用双层循环,外层循环针对除了第一个元素之外的所有元素,内层循环针对当前元素前面的有序表进行…...
Springboot框架集成Websocket通信方式
Websocket实现了“服务器”主动向“客户端”发送数据,改变了以往通过轮询、长轮训、长连接等方式获取服务器端数据的方式。 一、Websocket有三种不同的用场景,单播、广播和组播; (一)、单播(Unicast) 单播是客户端与服务器之间的“一对一”的连接。是在一个单个的发送…...
将json数据分组
在工作中有时需要根据业务需要,将大量数据进行处理分成几个一组 // 例如要将下方数据进行处理 var stuCount [{"id": "1612321835288","libraryCode": "D","regionCode": "A","positionCode&qu…...
从零开始实现一个C++高性能服务器框架----Socket模块
此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善 项目地址:https://gitee.com/lzhiqiang1999/server-framework 简介 项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度&am…...
ld: library not found for -lcrt0.o
ld: library not found for -lcrt0.o 背景: Mac 系统编译的时候报错 语言:golang 原因: 代码使用了静态编译,-static。stack overflow 上说 This option will not work on Mac OS X unless all libraries (including libgcc.a…...
接口测试和功能测试的区别有哪些?说一些你不知道的知识
目录 接口测试和功能测试的区别 目的 测试范围 测试方法 重要性 编辑 举个例子 对于接口测试 对于功能测试 编辑 总结 接口测试和功能测试是软件测试中的两种常见测试类型,主要用于评估软件系统的质量。尽管这两种测试都是为了评估软件系统的性…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
