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…...
接口测试和功能测试的区别有哪些?说一些你不知道的知识
目录 接口测试和功能测试的区别 目的 测试范围 测试方法 重要性 编辑 举个例子 对于接口测试 对于功能测试 编辑 总结 接口测试和功能测试是软件测试中的两种常见测试类型,主要用于评估软件系统的质量。尽管这两种测试都是为了评估软件系统的性…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
