当前位置: 首页 > news >正文

Python常见装饰器使用(实用向)

目录

    • 1.`@staticmethod`
    • 2.`@classmethod`
    • 3、`@classmethod` 与`@staticmethod`比较
    • 4. `@property`
    • 5.`@abstractmethod`
    • 6.`@wraps`
    • 7.`@lru_cache`
    • 8.`@timeout`
    • 9.`@retry`

  1. @staticmethod:将一个方法转换为静态方法,可以在不创建类实例的情况下调用。
  2. @classmethod:将一个方法转换为类方法,可以在不创建类实例的情况下调用,并且可以访问类的属性和方法。
  3. @property:将一个方法转换为属性,可以像访问属性一样访问方法,而不需要使用括号调用。
  4. @abstractmethod:定义一个抽象方法,子类必须实现该方法才能被实例化。
  5. @wraps:将一个函数的元信息(如函数名、文档字符串、参数列表等)复制到另一个函数中,可以避免装饰器对函数元信息的影响。
  6. @lru_cache:使用 LRU 算法实现的缓存装饰器,可以缓存函数的计算结果,避免重复计算。
  7. @timeout:设置函数的最大执行时间,如果函数执行时间超过设定的时间,就会抛出 TimeoutError 异常。
  8. @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比较

classmethodstaticmethod 都是 Python 中的装饰器,用于定义类方法和静态方法。虽然它们都可以在类中定义方法,通过类名直接调用,而不需要创建类的实例,但是它们有一些不同之处。

不同点:

  1. classmethod 的第一个参数是类本身,通常命名为 cls,而 staticmethod 没有特殊的参数。
  2. classmethod 可以访问和修改类的属性和方法,而 staticmethod 只能访问类的属性和方法,不能修改它们。
  3. classmethod 可以被子类继承和重写,而 staticmethod 不会被继承和重写。

以下是一个简单的示例代码,演示了如何使用 classmethodstaticmethod

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&#xff1a;将一个方法转换为静态方法&#xff0c;可以在不创建类实例的情况下调用。classmethod&#xff1a;将一个方法转换为…...

集合详解之(三)单列集合接口Set及具体子类HashSet、TreeSet

文章目录&#x1f412;个人主页&#x1f3c5;JavaSE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;Set集合接口&#x1f380;HashSet实现类&#x1f380;TreeSet实现类&#x1fa85;HashSet类常用方法&#xff1a;&#x1fa85;TreeSet类常用方法&#xff1a;&#x1f41…...

力扣刷题笔记22—— 矩阵中的路径(回溯)/pair的学习

矩阵中的路径&#xff08;回溯&#xff09;/pair的学习问题分析示例代码pair学习问题 来自力扣&#xff1a; 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按…...

Spring学习1

一、Spring简介 Spring翻译过来就是春天的意思&#xff0c;其实也就是给软件行业带来了春天2002年&#xff0c;首次推出Spring框架的雏形&#xff0c;interface21框架Spring框架就是以interface21框架为基础&#xff0c;经过重新设计&#xff0c;并不断丰富&#xff0c;在2004年…...

Keep再闯IPO,三年亏损16亿,会员留存率跌破70%

“运动科技第一股”来了&#xff1f; 3月28日&#xff0c;线上健身平台的运营方、北京卡路里科技有限公司&#xff08;下称“Keep”&#xff09;更新招股书&#xff0c;再次闯关港股IPO。 Keep是一家在线健身平台&#xff0c;主要产品包括在线健身内容、智能健身设备和配套运…...

软件测试分类详解

一图看清软件测试分类 一、按测试技术分&#xff08;是否查看代码&#xff09; **1. 黑盒测试**&#xff1a;软件功能是否正常使用【功能的测试】 **2. 白盒测试**&#xff1a;代码逻辑是否正确【结构的测试】 **3. 灰盒测试**&#xff1a;介于两者之间的测试&#xff0c;也…...

网站怎么优化出排名

网站怎么优化出排名&#xff0c;独立站SEO优化应该怎么做&#xff1f;#独立站#推广优化#SEO优化 今天跟大家聊一下独立站的SEO&#xff0c;是指个人或者小型的企业对独立站进行一个优化&#xff0c;以提高他在搜索引擎中的排名和流量&#xff0c;从而吸引更多的这个客户和用户。…...

h5|web页面嵌套iframe传参给cocosCreator

h5|web页面嵌套iframe传参给cocosCreator 目录 一、快速浏览 二、详细实现与项目代码 三、安全性评估——iframe 实现效果: 一、快速浏览 在h5页面中&#xff0c;使用JavaScript获取需要传递的参数&#xff0c;如下&#xff1a; var token ZHESHINIDETOKEN; var phone 11…...

阿里云安全产品Web应用防火墙是什么?有什么作用?

Web应用防火墙是一款网站Web应用安全的防护产品&#xff0c;拦截针对您网站发起的Web通用攻击&#xff08;如SQL注入、XSS跨站等&#xff09;或是应用资源消耗型攻击&#xff08;CC&#xff09;&#xff0c;同时也可以满足您网站从流量管理角度来防御业务风险&#xff0c;例如B…...

【SSM】Spring6(九.代理模式)

文章目录1.代理模式2. 静态代理3. 动态代理3.1 JDK动态代理3.2 CGLIB动态代理1.代理模式 代理模式主要有两种&#xff1a; 静态代理模式 动态代理模式 2. 静态代理 有这样一个业务&#xff1a;订单的生成&#xff0c;修改&#xff0c;查看详情。实现如下 package com.sdnu.…...

【1017. 负二进制转换】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个整数 n &#xff0c;以二进制字符串的形式返回该整数的 负二进制&#xff08;base -2&#xff09;表示。 注意&#xff0c; 除非字符串就是 "0"&#xff0c;否则返回的字符串中不…...

C语言实现插入排序与希尔排序

目录 一&#xff0c;插入排序 插入排序C语言实现&#xff08;升序&#xff09; 1&#xff0c;将新元素插入到有序序列 2&#xff0c;循环的开始与终止 二&#xff0c;希尔排序 希尔排序C语言实现&#xff08;升序&#xff09; 1&#xff0c;单趟&#xff1a; 2&#x…...

第九章-DOM与CSS

style属性 文档中每个元素节点都有一个属性style。style属性包含着元素样式&#xff0c;查询这个属性将返回一个对象而不是一个简单的字符串。样式都存放在这个style对象的属性里。 var element getElementById("example") //查看颜色属性 element.style.color //…...

蓝桥杯真题练习

小蓝在玩一个寻宝游戏, 游戏在一条笔直的道路上进行, 道路被分成了 nn 个方格, 依次编号 1 至 nn, 每个方格上都有一个宝物, 宝物的分值是一个整数 (包括正数、负数和零), 当进入一个方格时即获得方格中宝物的分值。小蓝可 以获得的总分值是他从方格中获得的分值之和。 小蓝开始…...

插入排序的简单理解

详细描述 插入排序的基本思想是&#xff1a;将一个记录插入到已经排好序的有序表中&#xff0c;从而得到一个新的、记录数增 1 的有序表。 在其实现过程中使用双层循环&#xff0c;外层循环针对除了第一个元素之外的所有元素&#xff0c;内层循环针对当前元素前面的有序表进行…...

Springboot框架集成Websocket通信方式

Websocket实现了“服务器”主动向“客户端”发送数据,改变了以往通过轮询、长轮训、长连接等方式获取服务器端数据的方式。 一、Websocket有三种不同的用场景,单播、广播和组播; (一)、单播(Unicast) 单播是客户端与服务器之间的“一对一”的连接。是在一个单个的发送…...

将json数据分组

在工作中有时需要根据业务需要&#xff0c;将大量数据进行处理分成几个一组 // 例如要将下方数据进行处理 var stuCount [{"id": "1612321835288","libraryCode": "D","regionCode": "A","positionCode&qu…...

从零开始实现一个C++高性能服务器框架----Socket模块

此项目是根据sylar框架实现&#xff0c;是从零开始重写sylar&#xff0c;也是对sylar丰富与完善 项目地址&#xff1a;https://gitee.com/lzhiqiang1999/server-framework 简介 项目介绍&#xff1a;实现了一个基于协程的服务器框架&#xff0c;支持多线程、多协程协同调度&am…...

ld: library not found for -lcrt0.o

ld: library not found for -lcrt0.o 背景&#xff1a; Mac 系统编译的时候报错 语言&#xff1a;golang 原因&#xff1a; 代码使用了静态编译&#xff0c;-static。stack overflow 上说 This option will not work on Mac OS X unless all libraries (including libgcc.a…...

接口测试和功能测试的区别有哪些?说一些你不知道的知识

目录 接口测试和功能测试的区别 目的 测试范围 测试方法 重要性 ​编辑 举个例子 对于接口测试 对于功能测试 ​编辑 总结 接口测试和功能测试是软件测试中的两种常见测试类型&#xff0c;主要用于评估软件系统的质量。尽管这两种测试都是为了评估软件系统的性…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...