Python编码系列—Python装饰器:编写可复用功能的魔法棒

news2024/9/30 19:34:27

🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中一起航行,共同成长,探索技术的无限可能。

🚀 探索专栏:学步_技术的首页 —— 持续学习,不断进步,让学习成为我们共同的习惯,让总结成为我们前进的动力。

🔍 技术导航:

  • 人工智能:深入探讨人工智能领域核心技术。
  • 自动驾驶:分享自动驾驶领域核心技术和实战经验。
  • 环境配置:分享Linux环境下相关技术领域环境配置所遇到的问题解决经验。
  • 图像生成:分享图像生成领域核心技术和实战经验。
  • 虚拟现实技术:分享虚拟现实技术领域核心技术和实战经验。

🌈 非常期待在这个数字世界里与您相遇,一起学习、探讨、成长。不要忘了订阅本专栏,让我们的技术之旅不再孤单!

💖💖💖 ✨✨ 欢迎关注和订阅,一起开启技术探索之旅! ✨✨

文章目录

  • 1. 背景介绍
  • 2. 原理解析
  • 3. 使用场景
  • 4. 代码样例
  • 5. 总结

1. 背景介绍

在Python编程的奇妙世界里,装饰器以其独特的魅力,成为了代码增强的强大工具。它们允许我们在不直接修改函数代码的前提下,为函数注入新的活力。本文将带您领略装饰器的魔力,从基础概念到高级应用,结合实战案例,深入探索装饰器的神秘面纱。

装饰器是Python中一种设计模式,用于扩展或修改函数或类的功能。它通过函数的嵌套和高阶函数实现,是一种典型的元编程技术。装饰器的使用,让代码更加模块化,提高了代码的复用性。
在这里插入图片描述

2. 原理解析

装饰器可以在不修改原有函数代码的情况下,给函数增加新的功能。这就像是给函数穿上了一件“外衣”,在函数执行前后可以添加额外的操作。

装饰器的基本结构:

def my_decorator(func):
    def wrapper(*args, **kwargs):
        # 在这里可以执行一些额外的代码
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)  # 调用原始函数
        print("Something is happening after the function is called.")
        return result
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

在这个例子中,my_decorator 是一个装饰器,它接收一个函数 func 作为参数,并返回一个新的函数 wrapperwrapper 函数在调用原始函数 func 之前和之后分别打印了一些文本。say_hello 函数被 @my_decorator 装饰后,每次调用 say_hello 都会执行 wrapper 函数中的代码。

functools.wraps 的使用:
当我们使用装饰器时,原始函数的名称和文档字符串可能会丢失。为了保留这些信息,我们可以使用 functools.wraps,这是一个专门用于装饰器的装饰器,它可以将原始函数的元数据复制到包装函数中。

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 装饰器逻辑
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def say_hello():
    """Greet the world."""
    print("Hello!")

使用 @wraps(func) 后,即使 say_hello 函数被 wrapper 函数所包装,我们仍然可以通过 say_hello.__name__ 获取到函数名,通过 say_hello.__doc__ 获取到文档字符串。

带参数的装饰器:
装饰器也可以有参数,这允许我们根据不同的条件来定制装饰器的行为。

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def say_hello():
    print("Hello!")

say_hello()  # 输出 "Hello!" 三次

类装饰器:
装饰器不仅限于函数,还可以是类。类装饰器是一种包含 __call__ 方法的类,它允许类的实例在调用时表现得像函数。

class DecoratorClass:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Something is happening before the function is called.")
        result = self.func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result

@DecoratorClass
def say_hello():
    print("Hello!")

装饰器的高级应用:
装饰器可以嵌套使用,也可以用于类和方法。它们在Web框架中非常常见,用于处理路由、请求验证、权限控制等。

3. 使用场景

装饰器在Python中是一种非常强大的工具,它允许我们在不修改原有函数代码的情况下,动态地增加或修改函数的功能。以下是一些具体的应用场景,通过实际的代码示例和项目案例,我们可以更深入地理解装饰器的广泛应用:

  1. 日志记录:装饰器可以用于记录函数的调用日志,包括函数名、参数值等,这对于调试和追踪函数的执行非常有帮助。例如,使用装饰器记录函数调用的详细日志,可以方便地监控函数的使用情况 。

  2. 性能测试:通过装饰器测量函数执行时间,用于性能分析。例如,创建一个装饰器 calculate_execution_time 来统计任何函数的执行时间 。

  3. 事务处理:在Web应用中,使用装饰器实现事务性操作,确保数据库操作的原子性。例如,在Flask框架中,通过装饰器控制服务层的事务,使得在出现异常时能够回滚更改 。

  4. 缓存:使用装饰器对函数结果进行缓存,避免重复计算。Python内置的 functools.lru_cache 就是一个常用的缓存装饰器,它可以缓存最近使用过的结果,提高程序的运行效率 。

  5. 权限校验:在需要保护的函数或方法前使用装饰器进行权限验证,确保只有具有相应权限的用户才能访问特定资源。例如,创建一个 require_permission 装饰器来封装权限验证逻辑 。

  6. 输入验证:确保函数接收到的输入是有效的,如果输入不符合预期,可以拒绝执行并提供错误信息 。

  7. 错误处理:通过装饰器统一处理函数可能抛出的异常,避免在每个函数中重复错误处理的代码 。

  8. 单例模式:使用装饰器确保某个类只有一个实例,如果实例已存在则直接返回该实例,而不是创建新的实例 。

  9. API请求限制:在API开发中,使用装饰器限制请求的频率,防止滥用和过载 。

  10. 事件监听:在特定事件发生时,使用装饰器执行额外的操作或处理 。

通过这些实际应用场景,我们可以看到装饰器在Python编程中的多样化用途。它们不仅提高了代码的复用性,还使代码更加简洁和易于维护。

4. 代码样例

以下是一个简单的装饰器示例,用于记录函数的执行时间:

from functools import wraps
import time

def time_logger(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} executed in {end_time - start_time} seconds")
        return result
    return wrapper

@time_logger
def some_function():
    # 模拟长时间运行的函数
    time.sleep(2)

some_function()  # 输出执行时间

考虑一个Web应用,需要对用户请求进行登录验证。我们可以使用装饰器来实现:

from functools import wraps

def login_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not user_logged_in():
            raise Exception("You must be logged in to perform this action.")
        return f(*args, **kwargs)
    return decorated

@login_required
def view_dashboard():
    # 需要登录后才能访问的代码
    pass

5. 总结

Python装饰器是一种强大的代码增强工具,它提供了一种优雅的方式来扩展函数或类的功能,而无需修改其原有代码。通过本文的学习,您应该能够理解装饰器的基本概念、工作原理以及如何在实际项目中应用装饰器。装饰器不仅提高了代码的可读性和可维护性,而且使得代码更加模块化和可重用。

🌟 在这篇博文的旅程中,感谢您的陪伴与阅读。如果内容对您有所启发或帮助,请不要吝啬您的点赞 👍🏻,这是对我最大的鼓励和支持。

📚 本人虽致力于提供准确且深入的技术分享,但学识有限,难免会有疏漏之处。如有不足或错误,恳请各位业界同仁在评论区留下宝贵意见,您的批评指正是我不断进步的动力!😄😄😄

💖💖💖 如果您发现这篇博文对您的研究或工作有所裨益,请不吝点赞、收藏,或分享给更多需要的朋友,让知识的力量传播得更远。

🔥🔥🔥 “Stay Hungry, Stay Foolish” —— 求知的道路永无止境,让我们保持渴望与初心,面对挑战,勇往直前。无论前路多么漫长,只要我们坚持不懈,终将抵达目的地。🌙🌙🌙

👋🏻 在此,我也邀请您加入我的技术交流社区,共同探讨、学习和成长。让我们携手并进,共创辉煌!
在这里插入图片描述

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

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

相关文章

kafka零拷贝sendfile及mmap简述

概述 通常在选型比较消息中间件时,都会在备选栏有kafka; kafka突出的特点就是高吞吐,零拷贝; 这里的零拷贝其实就是内核和用户空间之间没有copy,并不是真的0拷贝; 毕竟数据在磁盘,要读到网卡发…

Linux源码阅读笔记19-插入删除模块实战

前面已经讲了Linux模块的基本知识&#xff0c;现在我们来熟悉一下模块相关的基本操作。 模块的编写 #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h>// 插入内核时的函数 static int __init lnm_init(void) {printk("h…

CAN通信(速记版)

CAN 总线简介 CAN 协议经过 ISO 标准化后有两个标准:ISO11898 标准和 ISO11519-2 标准。前者适用通信速率为 125Kbps~1Mbps 场景,后者适用 125Kbps 以下场景。 STM32 自带基本扩展 CAN(bxCAN)。它支持 CAN 协议 2.0A 和 2.0B,都属于11898标准。支持最高传输速率为1 Mbps。CA…

2024河南萌新联赛第(四)场 河南理工大学

B.小雷的神奇电脑 题目&#xff1a; 原题链接 给出量个数n,m&#xff0c;一个有n个数的数组&#xff0c;数组里每个数不超过2^m&#xff0c;求数组任意两个数同或后的最大值。同或定义&#xff1a;二进制下相同为1&#xff0c;不同为0。 思路&#xff1a; 观察同或的定义可…

第十二章:设置pod和容器权限-保障集群内节点和⽹络安全

本章内容包括&#xff1a; 在pod中使用宿主机节点的默认Linux命名空间以不同用户身份运行容器运行特权容器添加或禁用容器内核功能定义限制pod行为的安全策略保障pod的网络安全 谈到了如何保障API服务器的安全。如果攻击者获得了访问API服务器的权限&#xff0c;他们可以通过在…

虹科新品 | PDF记录仪新增蓝牙®接口型号HK-LIBERO CL-Y

新品发布&#xff01;HK-LIBERO CE / CH / CL产品家族新增蓝牙接口型号HK-LIBERO CL-Y&#xff01; PDF记录仪系列新增蓝牙接口型号 HK-LIBERO CL-Y HK-LIBERO CE、HK-LIBERO CH和HK-LIBERO CL&#xff0c;虹科ELPRO提供了一系列高品质的蓝牙&#xff08;BLE&#xff09;多用途…

锂电池充电板电路设计

写这篇文章的目的主要是个人经验的总结&#xff0c;希望能给开发者们提供一种锂电池充电电路以及电源显示的电路思路。接下来从以下几个方面讲述电路。 设计这款电路的初衷是想用一块硬币大小的锂电池作为供电电源&#xff08;3.5V-4.2V&#xff09;&#xff0c;降压供给3.3V电…

c语言学习,isalpha()函数分析

1&#xff1a;isalpha() 函数说明&#xff1a; 检测参数c&#xff0c;是否为英文字母 2&#xff1a;函数原型&#xff1a; int isalpha(int c) 3&#xff1a;函数参数&#xff1a; 参数c&#xff0c;为检测英文字母 4&#xff1a;返回值&#xff1a; 参数c为字母&#xff0c…

Java封装原生ES

文章目录 &#x1f31e; Sun Frame&#xff1a;SpringBoot 的轻量级开发框架&#xff08;个人开源项目推荐&#xff09;&#x1f31f; 亮点功能&#x1f4e6; spring cloud模块概览常用工具 &#x1f517; 更多信息1.spring-data-es操作ES1.引入依赖2.application.yml配置uris3…

浮点数及其计算

目录 引言 1.浮点数的表示 1.1浮点数的作用和基本原理 1.2浮点数规格化 左规 右规 2.IEEE 754 标准 2.1图示&#xff1a; 2.2 阶码的全零全一有特殊含义: 2.3 IEEE 754 表示的范围&#xff1a; 2.4 十进制转IEEE 754&#xff1a; 2.5 IEEE 754转十进制&#xff1a…

Electron-builder 打包

项目比较简单&#xff0c;仅使用了 Electron 原生js 安装 electron-builder npm install electron-builder --dev配置 package.json 中的打包命令 {"script":{// ..."dev": "electron .","pack": "electron-builder"} }添…

【QT】Qt 音视频

Qt 音视频 Qt 音视频1. Qt 音频2. Qt 视频 Qt 音视频 在 Qt 中&#xff0c;音频主要是通过 QSound 类来实现。但是需要注意的是 QSound 类只支持播放 wav 格式的音频文件。也就是说如果想要添加音频效果&#xff0c;那么首先需要将非 wav 格式的音频文件转换为 wav 格式。 通…

MySQL 5.7 DDL 与 GH-OST 对比分析

作者&#xff1a;来自 vivo 互联网存储研发团队- Xia Qianyong 本文首先介绍MySQL 5.7 DDL以及GH-OST的原理&#xff0c;然后从效率、空间占用、锁阻塞、binlog日志产生量、主备延时等方面&#xff0c;对比GH-OST和MySQL5.7 DDL的差异。 一、背景介绍 在 MySQL 数据库中&…

普元Devops学习笔记-devops构建后jenkins流水线sleep 1hr 23min的问题

1 背景 java项目命名为 simple2。 命名有点随意&#xff0c;不要在意这个&#xff0c;不重要。 simple2的代码维护在gitlab中。 simple2项目有两个git分支&#xff1a; dev 和 master 开发中的代码在 dev分支&#xff0c;dev分支需要合并(merge)到master主分支。 基于此目…

电机控制器遇上第三代半导体,杀手锏是什么?

导语 华东电机控制器市场的创新方向&#xff0c;文中参考答案都有了。 前言 随着工业自动化和智能化进程的加速推进&#xff0c;电机控制器作为驱动系统的核心部件&#xff0c;在推动产业升级转型中扮演着至关重要的角色。华东电机控制器市场以其独特的优势异军突起&#xff0c…

【C++ STL】unordered_mapunordered_set (哈希表)

文章目录 unordered_map&unordered_set1. unordered容器1.1 效率对比 2. 哈希2.1 哈希的定义哈希函数除留余数法自定义哈希函数 哈希冲突 2.2 哈希冲突的解决闭散列/开放定址法两种探测方式闭散列扩容 开散列/拉链法/哈希桶开散列实现 3. 模拟实现3.1 改造哈希表3.2 封装容…

GPIO输入模式之按键控制及光敏传感器控制应用案例

系列文章目录 STM32之GPIO&#xff08;General Purpose Input/Output&#xff0c;通用型输入输出&#xff09; GPIO输出控制之LED闪烁、LED流水灯以及蜂鸣器应用案例 文章目录 系列文章目录前言一、按键简介二、传感器模块简介2.1 AO模拟量输出模块2.2 DO数字量输出模块2.3 指…

【C语言加油站】数据在内存中的存储

数据在内存中的存储 导读一、计算机中的数据类型二、整数在计算机中的存储2.1 整数的存储形式——原码、反码与补码2.2 三种形式之间的相互转换2.3 采用补码存储整数的原因 三、大小端字节序与字节序判断3.1 大端存储与小端存储3.2 为什么会出现大小端存储&#xff1f;3.3 大端…

家用设备轻松搭建 AI 集群,畅跑 Llama 3.1 405B

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话: 本文主要介绍如何在家用设备上运行大型开源语言模型Llama 3.1 405B,首先我会解释构建人工智能集群来提高运行效率的原理,随后会演示如何通过Distributed Llama项目支持在多个设备上运行LLM模型,并…

【STL】05.vector的模拟实现

一、vector的实现 1.1 基本框架 template<class T> class vector {typedef T* iterator;typedef const T* const_iterator; public:private:iterator _startnullptr;iterator _finishnullptr;iterator _end_of_storagenullptr; };1.2 vector的默认成员函数 1.2.1 构造…