python装饰器

装饰器是 Python 中一个非常强大和灵活的特性,用于修改或扩展函数或方法的行为。装饰器本质上是一个高阶函数,它可以接受一个函数作为参数,并返回一个新的函数。装饰器通常用于日志记录、性能测试、事务处理、缓存、权限校验等场景。

基本概念

高阶函数:接受一个或多个函数作为输入,或者输出一个函数的函数。

闭包:一个函数对象,记住了它被定义时的自由变量的值。‍

基本装饰器

定义装饰器

装饰器通常定义为一个外层函数,这个外层函数返回一个内层函数。内层函数负责执行实际的装饰逻辑。

def my_decorator(func):    def wrapper():        print("Something is happening before the function is called.")        func()        print("Something is happening after the function is called.")    return wrapper@my_decoratordef say_hello():    print("Hello!")say_hello()

装饰器的工作原理

@符号:@decorator 是装饰器的语法糖,等价于 say_hello = my_decorator(say_hello)。

调用过程:​​​​​​​

say_hello 被传递给 my_decorator。my_decorator 返回 wrapper 函数。say_hello 现在指向 wrapper 函数。当调用 say_hello() 时,实际上是调用 wrapper()。

带参数的装饰器

有时候,我们希望装饰器本身也能接受参数。这可以通过再嵌套一层函数来实现。​​​​​​​

def repeat(num_times):    def decorator(func):        def wrapper(*args, **kwargs):            for _ in range(num_times):                result = func(*args, **kwargs)            return result        return wrapper    return decorator@repeat(3)def greet(name):    print(f"Hello, {name}!")greet("Alice")

保留元数据

使用装饰器后,原始函数的元数据(如名称、文档字符串等)会被覆盖。为了保留这些元数据,可以使用 functools.wraps。​​​​​​​

import functoolsdef my_decorator(func):    @functools.wraps(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_decoratordef say_hello():    """Say hello to the user."""    print("Hello!")print(say_hello.__name__)  # 输出: say_helloprint(say_hello.__doc__)   # 输出: Say hello to the user.

类装饰器

除了函数装饰器,Python 还支持类装饰器。类装饰器通常用于修改类的行为。​​​​​​​

def add_class_method(cls):    def decorator(func):        setattr(cls, func.__name__, func)        return cls    return decorator@add_class_methodclass MyClass:    passdef say_hello(self):    print("Hello from MyClass!")instance = MyClass()instance.say_hello()  # 输出: Hello from MyClass!

装饰器组合

可以将多个装饰器应用于同一个函数。装饰器的执行顺序是从内到外。

def decorator1(func):    def wrapper():        print("Decorator 1")        func()    return wrapperdef decorator2(func):    def wrapper():        print("Decorator 2")        func()    return wrapper@decorator1@decorator2def say_hello():    print("Hello!")say_hello()# 输出:# Decorator 1# Decorator 2# Hello!

带状态的装饰器

有时候,我们希望装饰器能够记住一些状态信息。这可以通过使用类来实现。

class Counter:    def __init__(self, func):        self.func = func        self.count = 0    def __call__(self, *args, **kwargs):        self.count += 1        print(f"Function {self.func.__name__} has been called {self.count} times")        return self.func(*args, **kwargs)@Counterdef say_hello():    print("Hello!")say_hello()  # 输出: Function say_hello has been called 1 timessay_hello()  # 输出: Function say_hello has been called 2 times

实际应用

日志记录​​​​​​​

import loggingdef log_function_call(func):    def wrapper(*args, **kwargs):        logging.info(f"Calling {func.__name__} with args={args} kwargs={kwargs}")        result = func(*args, **kwargs)        logging.info(f"{func.__name__} returned {result}")        return result    return wrapper@log_function_calldef add(a, b):    return a + badd(3, 5)

缓存​​​​​​​

from functools import lru_cache@lru_cache(maxsize=128)def fibonacci(n):    if n <= 1:        return n    return fibonacci(n - 1) + fibonacci(n - 2)print(fibonacci(10))  # 输出: 55

总结

装饰器是 Python 中一个非常强大的工具,可以用来增强或修改函数和类的行为。通过理解和使用装饰器,你可以编写更加简洁、模块化和可维护的代码。

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

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

相关文章

特殊矩阵的压缩存储

一维数组的存储结构 ElemType arr[10]; 各数组元素大小相同&#xff0c;且物理上连续存放。 数组元素a[i]的存放地址 LOC i * sizeof(ElemType)。&#xff08;LOC为起始地址&#xff09; 二维数组的存储结构 ElemType b[2][4];二维数组也具有随机存取的特性&#xff08;需…

中立性DEA交叉效率评价方法

今天推出中立性DEA模型的计算工具 参考文献&#xff1a;《中立性DEA交叉效率评价方法》袁剑波&#xff0c;吴立辉&#xff0c;魏思 中立性DEA交叉效率评价方法 在数据包络分析&#xff08;DEA&#xff09;对决策单元效率评价的方法中&#xff0c;对抗性DEA交叉效率方法把所有…

【Visual Studio】解决 CC++ 控制台程序 printf 函数输出中文和换行符显示异常

问题描述 C&C 控制台程序 printf 函数输出中文和换行符 \n 显示异常。 #include <stdio.h>int main() {int choice;printf("菜单:\n");printf("1. 选项一\n");printf("2. 选项二\n");printf("3. 选项三\n");printf("…

【dvwa靶场:XSS系列】XSS (Stored)低-中-高级别,通关啦

更改name的文本数量限制大小&#xff0c; 其他我们只在name中进行操作 【除了低级可以在message中进行操作】 一、低级low <script>alert("假客套")</script> 二、中级middle 过滤了小写&#xff0c;咱们可以大写 <Script>alert("假客套…

【Linux】深入理解进程控制:从创建到终止和进程等待

文章目录 进程创建fork函数如何用fork函数创建子进程写实拷贝 进程终止错误信息exit_exit 进程等待waitwaitpid 总结 进程创建 fork函数 fork 函数是 Unix/Linux 系统中用于创建新进程的系统调用。调用 fork 后&#xff0c;当前进程&#xff08;父进程&#xff09;会被复制&a…

【java】对象的内存存储

目录 对象在内存中的分配设计到的内存结构(理论)类中对象的内存解析创建类的一个对象&#xff0c;属性赋值创建类的多个对象&#xff0c;属性赋值 对象在内存中的分配设计到的内存结构(理论) 栈&#xff1a;方法内定义的变量&#xff0c;存储在栈中 堆&#xff1a;new出来的结…

【wrl2stl】WRL文件转STL文件-Python

之前有一篇博客写了Avizo自动化批量导出wrl文件&#xff1a;【Avizo&Python】离散颗粒的分割、网格化与单颗粒批量自动保存wrl文件_avizo python-CSDN博客 还有一篇写了wrl转为xyz格式文件&#xff1a; Wrl文件转XYZ文件-Python_python 打开wrl三维模型-CSDN博客 在这篇…

【Linux系统编程】第三十九弹---探索信号处理的奥秘:阻塞信号与sigset_t的深入剖析及实战

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、信号处理 2、阻塞信号 2.1、信号其他相关常见概念 2.2、在内核中的表示 2.3、sigset_t 2.4、信号集操作函数 3、完整…

零基础Apifox测试FastAPI接口入门

文章目录 一、FastAPI部分二、Apifox部分1、安装Apifox2、创建接口3、更改测试环境4、发送请求 一、FastAPI部分 python使用fastapi编写接口内容&#xff08;文件名&#xff1a;text.py&#xff09;&#xff1a; from fastapi import FastAPI import uvicornapp FastAPI()ap…

Linux终端退出程序后,TCP地址仍被占用

报错如下&#xff1a; Error on binding: Address already in use 这是一个正在运行的服务器&#xff0c;运行在linux的终端。上一次我使用CtrlZ退出这个程序&#xff0c;再次./my_server想运行这个程序时&#xff0c;出现这个报错。这是由两点原因&#xff1a; 1、守护进程或…

嵌入式通信协议:IIC简明学习笔记

IIC学习笔记 IIC特点 1.适合 小数据场合使用&#xff0c;传输距离短。 2.只能有一个主机。 3.标准IIC速度为100kHZ&#xff0c;高速IIC一般可达400kHZ以上。 4.SCL和SDA都需要接上拉电阻&#xff08;大小由速度和容性负载决定&#xff0c;一般在3.3k-10k之间&#xff09;。 5…

基于anaconda的python3.6安装opencv4.1.15

opencv-python一些新版本由于部分函数涉及专利问题&#xff0c;如sift和surf&#xff0c;有些功能不能很好地被使用&#xff0c;所以最好使用opencv-python 3.4.1.15版本的。 下载地址分别为&#xff1a; 1、https://pypi.tuna.tsinghua.edu.cn/simple/opencv-python/ 查找…

【自制操作系统】0x01MBR

环境 ubuntu 20.04 gcc 9.4.0&#xff08;加载硬盘程序之前都是&#xff0c;最后可能会切换到 gcc 4.4&#xff09; bochs 2.7 bochs 配置 bochs 安装之前文章记录过&#xff0c;现在记录一下本次使用的bochs配置 bochsrc #第一步&#xff0c;首先设置 Bochs 在运行过程中…

SpringBoot接入星火认知大模型

文章目录 准备工作整体思路接入大模型服务端和大模型连接客户端和服务端的连接测试 准备工作 到讯飞星火大模型上根据官方的提示申请tokens 申请成功后可以获得对应的secret&#xff0c;key还有之前创建的应用的appId&#xff0c;这些就是我们要用到的信息 搭建项目 整体思…

ssm056基于Java语言校园快递代取系统的设计与实现+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;校园快递代取系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园快递代取系统…

简单语音信号识别的MATLAB仿真

简单语音信号识别的MATLAB仿真 摘要&#xff1a; 隐马尔可夫模型&#xff08;HMM&#xff09;作为描述语音信号的一种统计模型&#xff0c;在现代语音处理中获得了广泛应用。本文概述了基于HMM的语音识别技术&#xff0c;阐述了预处理&#xff0c;特征提取以及训练&#xff0c…

童年玩具:两款线绳陀螺

1,2图是过去用来安装明线电线的瓷夹。现在应该找不到了。过去安装电线后&#xff0c;家里留下了一些&#xff0c;拿来做线陀螺非常好。 因为它非常重&#xff0c;旋转起来很有力&#xff0c;那声音呼呼响。 3,4图是现在都能看到的一个圆木片&#xff0c;两个孔&#xff0c;穿绳…

AntFlow一款开源免费且自主可控的仿钉钉工作流引擎

在现代企业管理中&#xff0c;流程审批的高效性直接影响到工作的流畅度与生产力。最近&#xff0c;我发现了一个非常有趣的项目——AntFlow。这个项目不仅提供了一个灵活且可定制的工作流平台&#xff0c;还能让用户以可视化的方式创建和管理审批流程。 如果你寻找一个快速集成…

光纤资源APP开发及二次开发说明

光纤资源APP主要由以下几部分组成&#xff1a; 登录界面选择项目界面地图创建节点界面填写详细信息界面成端及端口表界面接续及接续表界面 其中1、2、4界面不需要涉及到ht&#xff0c;故用原生界面即可实现&#xff0c;但是3、5、6涉及到ht&#xff0c;而ht在app中是不兼容的…

鉴源实验室·如何通过雷达攻击自动驾驶汽车-针对点云识别模型的对抗性攻击的科普

01 引 言 随着自动驾驶技术的迅速发展&#xff0c;雷达和激光雷达等传感器在自动驾驶汽车中的作用愈发重要。它们能够生成3D点云数据&#xff0c;帮助车辆实时感知周围环境并做出安全决策。然而&#xff0c;尽管这些传感器对驾驶环境的检测非常精确&#xff0c;它们也面临一种…