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

Python装饰器:从入门到精通

目录

一、装饰器的本质与定义

二、装饰器的雏形与语法糖

1. 装饰器的雏形

2. 装饰器的语法糖

三、装饰器的常见应用

1. 获取程序的执行时间

2. 处理带参数的函数

3. 处理有返回值的函数

四、通用版本的装饰器

五、装饰器的高级用法

1. 给装饰器传递参数

六、总结


在 Python 的进阶特性中,装饰器无疑是一颗璀璨的明珠。它能够在不改变函数源代码和调用方式的前提下,为函数增添新的功能,是代码复用和功能扩展的绝佳方案。

一、装饰器的本质与定义

装饰器的本质是一个闭包函数,这意味着它满足闭包的三个构成条件:有嵌套、有引用、有返回(返回的是函数的内存地址)。简单来说,装饰器就是这样一种工具:在不改变现有函数源代码以及函数调用方式的前提下,实现给函数增加额外的功能。

二、装饰器的雏形与语法糖

1. 装饰器的雏形

最初的装饰器实现,需要手动将被装饰的函数传入装饰器函数,并重新赋值。例如,要给评论和下载功能添加登录验证,可这样实现:

def check(fun):def inner():print('登录功能')fun()return innerdef comment():print('评论功能')
comment = check(comment)
comment()def download():print('下载功能')
download = check(download)
download()

这里的check函数就是一个装饰器雏形,它接收要装饰的函数fun作为参数,内部嵌套的inner函数实现了额外的登录功能,并调用了原函数fun,最后返回inner函数。

2. 装饰器的语法糖

为了简化装饰器的使用,Python 提供了@语法糖。使用@装饰器的形式,可直接将装饰器应用于函数,无需手动赋值。例如:

def check(fun):def inner():print('验证登录')fun()return inner@check
def comment():print('发表评论')
comment()

此时,调用comment(),实际上是调用了装饰器内部的inner函数,先执行登录验证,再执行原函数的功能。

三、装饰器的常见应用

1. 获取程序的执行时间

装饰器可以轻松实现获取函数执行时间的功能。通过在函数执行前后记录时间戳,计算差值即可得到执行时间:

import time
def get_time(fun):def inner():begin = time.time()fun()end = time.time()print(f'这个函数的执行时间:{end - begin}')return inner@get_time
def demo():for i in range(1000000):print(i)
demo()

当调用demo()时,会自动计算并打印该函数的执行时间。

2. 处理带参数的函数

对于带有参数的函数,装饰器的内部函数可以使用*args和**kwargs来接收不定长参数,确保原函数的参数能正确传递:

def logging(fun):def inner(*args, **kwargs):print('-- 日志信息:正在努力计算机 --')fun(*args, **kwargs)return inner@logging
def sum_num(*args, **kwargs):result = 0for i in args:result += ifor i in kwargs.values():result += iprint(result)print(sum_num())

这样,sum_num函数可以接收任意数量的位置参数和关键字参数,装饰器也能正常工作。

3. 处理有返回值的函数

如果被装饰的函数有返回值,装饰器的内部函数需要将原函数的返回值返回,以保证函数功能的完整性:

def logging(fun):def inner(*args, **kwargs):print('-- 日志信息:正在努力计算 --')return fun(*args, **kwargs)return inner@logging
def sub_num(a, b):result = a - breturn resultprint(sub_num(20, 10))

调用sub_num(20,10)时,装饰器会返回原函数的计算结果。

四、通用版本的装饰器

综合考虑参数和返回值的情况,通用版本的装饰器应具备以下特点:有嵌套、有引用、有返回、有不定长参数、有 return 返回值。其代码示例如下:

def logging(fn):def inner(*args, **kwargs):print('-- 正在努力计算 --')return fn(*args, **kwargs)return inner@logging
def sum_num1(a, b):result = a + breturn result@logging
def sum_num2(a, b, c):result = a + b + creturn result

这个通用装饰器可以适用于各种类型的函数,无论是带参数还是有返回值的情况。

五、装饰器的高级用法

1. 给装饰器传递参数

通过在装饰器外侧再添加一个函数,专门用于接收参数,可以实现根据传递的参数不同,让装饰器表现出不同的功能。例如:

def logging(flag):def decorator(fun):def inner(*args, **kwargs):if flag == '+':print('-- 日志信息:正在努力进行加法运算 --')elif flag == '-':print('-- 日志信息:正在努力进行减法运算 --')return fun(*args, **kwargs)return innerreturn decorator@logging('+')
def sum_num(a, b):result = a + breturn resultprint(sum_num(2, 3))@logging('-')
def sub_num(a, b):result = a - breturn resultprint(sub_num(5, 2))

这里的logging函数接收参数flag,根据flag的值,装饰器会打印不同的日志信息。

六、总结

装饰器是 Python 中一种非常强大且优雅的特性,它基于闭包实现,能够在不改变原有函数的情况下为其增添功能。从简单的功能扩展到复杂的参数传递和类实现,装饰器展现出了极大的灵活性和实用性。掌握装饰器的使用,能够让我们的代码更加简洁、高效和可维护。

http://www.dtcms.com/a/338106.html

相关文章:

  • 【STM32】SPI 与 Flash 笔记
  • 【深度长文】Anthropic发布Prompt Engineering全新指南
  • 启发式合并
  • 1、代码相关优化建议
  • 数据分析进阶——解读文本分析模型【附全文阅读】
  • 第十六届蓝桥杯青少组C++省赛[2025.8.10]第二部分编程题(5、环形取硬币游戏)
  • 虚幻基础:动作时间窗
  • Kafka文件存储机制
  • 录音转文字,如何做到“快、准、狠“多格式通吃?
  • 自学中医笔记(二)
  • 大模型对齐算法(四): DAPO,VAPO,GMPO,GSPO, CISPO,GFPO
  • 如何平衡电竞酒店和高校宿舍对AI云电竞游戏盒子的不同需求?
  • 【Python】Python 多进程与多线程:从原理到实践
  • NVIDIA CWE 2025 上海直击:从 GPU 集群到 NeMo 2.0,企业 AI 智能化的加速引擎
  • 软件定义汽车---创新与差异化之路
  • C/C++ 中 str、str、*str 在指针语境下的具体含义(以 char* str 为例):
  • 深化中东战略承诺,联想集团宣布在利雅得设区域总部
  • wait / notify、单例模式
  • 【深度学习基础】PyTorch Tensor生成方式及复制方法详解
  • 【每日一题】Day 7
  • Linux——进程间、线程间的通信
  • 【C++】 using声明 与 using指示
  • 《彩色终端》诗解——ANSI 艺术解码(DeepSeek)
  • C++设计模式:建造者模式
  • 《若依》权限控制
  • ESP32小智-语音活动(VAD)检测流程
  • Pytorch GPU版本安装保姆级教程
  • 【Python面试题】描述一次解决内存泄漏的过程。如何用tracemalloc或者objgraph定位问题?什么情况下会用__slots__?
  • 【领码课堂】AI写码不再“盲跑”,方案先行,自动化高效落地
  • BOSS直聘招聘端AI辅助自动化技术研究