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…...

接口测试和功能测试的区别有哪些?说一些你不知道的知识
目录 接口测试和功能测试的区别 目的 测试范围 测试方法 重要性 编辑 举个例子 对于接口测试 对于功能测试 编辑 总结 接口测试和功能测试是软件测试中的两种常见测试类型,主要用于评估软件系统的质量。尽管这两种测试都是为了评估软件系统的性…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...