详细分析Python装饰器(附Demo)

news/2024/11/29 8:55:29/

目录

  • 前言
  • 1. 基本知识
  • 2. 无参装饰器
  • 3. 有参装饰器
  • 4. 多个装饰器

前言

装饰器类似Java的切点切面增强

推荐阅读:

  1. 详细分析Spring中的@Around注解(附Demo)
  2. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  3. Spring框架从入门到学精(全)

Python实战代码如下:

在这里插入图片描述

1. 基本知识

装饰器是Python语言中的一种高级功能,它允许将一个函数或者类“装饰”(即修改或增强)其他函数或者类的行为。装饰器本质上是一个可调用的对象,它接受一个函数或者类作为输入,并返回一个新的函数或者类

作用优点缺点
代码重用: 装饰器可以用来包装重复使用的功能或逻辑,提高代码的重用性

代码简洁: 装饰器可以将一些与主要逻辑无关的代码分离出来,使主要代码更加简洁易读

横切关注点(Cross-cutting Concerns): 装饰器可以用来处理与业务逻辑无关但又必须存在于多处的功能,例如日志记录、性能检测、权限验证等

动态增加功能: 装饰器可以在不修改被装饰对象的情况下,动态地增加新的功能或行为
提高代码的复用性和可维护性

使代码更加简洁,易于理解

允许动态地添加或修改对象的行为,而无需修改其原始定义
可能会增加代码的复杂性,特别是在使用多个装饰器的情况下

装饰器可能会改变被装饰对象的原始行为,导致难以调试

2. 无参装饰器

通过Demo了解如何增强

# 定义一个简单的装饰器函数 simple_decorator,接受一个函数作为参数
def simple_decorator(func):# 定义一个内部函数 wrapper,用于包装被装饰的函数def wrapper():print("Before calling the function")  # 在调用被装饰函数之前打印信息func()  # 调用被装饰的函数print("After calling the function")  # 在调用被装饰函数之后打印信息return wrapper  # 返回内部函数 wrapper# 使用装饰器 simple_decorator 对 say_hello 函数进行装饰
@simple_decorator
def say_hello():print("执行一次say_hello")  # 打印信息,表示 say_hello 函数被执行了一次# 调用被装饰后的 say_hello 函数,实际上会在函数执行前后打印额外的信息
say_hello()

截图如下:

在这里插入图片描述

3. 有参装饰器

额外添加了一个内部函数 decorator,它负责接收被装饰函数,并返回一个装饰器函数 wrapper。这种设计更符合装饰器的惯用方式,即装饰器函数接受参数(在这里是 n),然后返回一个装饰器函数,该装饰器函数再接受被装饰的函数,并返回一个新的函数(或者对原函数进行修改)

# 定义一个装饰器函数 repeat,接受一个参数 n,表示要重复执行的次数
def repeat(n):# 定义一个内部函数 decorator,该函数接受被装饰的函数作为参数 funcdef decorator(func):# 定义一个内部函数 wrapper,用于包装被装饰的函数,以实现重复执行的功能def wrapper(*args, **kwargs):# 使用 for 循环执行被装饰的函数 n 次for _ in range(n):func(*args, **kwargs)  # 调用被装饰的函数return wrapper  # 返回 wrapper 函数return decorator  # 返回 decorator 函数# 使用装饰器 repeat(3) 对 greet 函数进行装饰,表示要重复执行 3 次
@repeat(3)
def greet(name):print(f"Hello, {name}!")  # 打印输出问候语# 调用被装饰后的 greet 函数,实际上会重复打印三次问候语
greet("码农研究僧")

截图如下:

在这里插入图片描述

以下为错误显示:

def repeat(n):def wrapper(*args, **kwargs):func(*args, **kwargs)return wrapper@repeat(3)
def greet(name):print(f"Hello, {name}!")greet("码农研究僧")

装饰器 repeat 的内部函数 wrapper 中使用了 func(*args, **kwargs) 来调用被装饰的函数,但是在 repeat 函数内部并没有定义 func,因此会引发错误。正确的方式是在 repeat 内部定义一个参数来接收被装饰函数,并在 wrapper 中使用该参数来调用被装饰函数

4. 多个装饰器

以下代码整体逻辑如下:

  1. greet("manong") 被 bold 装饰器装饰,变成 bold(uppercase(greet))("manong")
  2. 首先 uppercase(greet) 被调用,得到大写的字符串 "HELLO, MANONG!"
  3. bold 装饰器再次被调用,将大写的字符串用 <b> 和 </b> 标签包裹起来,得到 <b>HELLO, MANONG!</b>
  4. 最终的结果被打印输出
# 定义装饰器 uppercase,将被装饰函数的返回值转换为大写
def uppercase(func):def wrapper(*args, **kwargs):print(2)# 调用被装饰函数,并将结果转换为大写result = func(*args, **kwargs)print(3)return result.upper()return wrapper# 定义装饰器 bold,将被装饰函数的返回值用 <b> 和 </b> 标签包裹起来
def bold(func):def wrapper(*args, **kwargs):print(1)# 调用被装饰函数,并用 <b> 和 </b> 标签包裹返回结果result = func(*args, **kwargs)print(4)return f"<b>{result}</b>"return wrapper# 先应用 bold 装饰器,再应用 uppercase 装饰器
@bold
@uppercase
def greet(name):return f"Hello, {name}!"# 调用 greet 函数,并输出结果
print(greet("manong"))

截图如下:

在这里插入图片描述

当函数 greet 被装饰时, uppercase 装饰器会先执行,然后是 bold 装饰器。这意味着 uppercase 装饰器的 wrapper 函数会先被调用,然后是 bold 装饰器的 wrapper 函数


http://www.ppmy.cn/news/1387353.html

相关文章

网络安全实训Day5

写在前面 昨天忘更新了......讲的内容不多&#xff0c;就一个NAT。 之前记的NAT的内容&#xff1a;blog.csdn.net/Yisitelz/article/details/131840119 网络安全实训-网络工程 NAT 公网地址与私网地址 公网地址 可以在互联网上被寻址&#xff0c;由运营商统一分配全球唯一的I…

git checkout不同分支时,为啥会把当前分支的修改内容也带到新分支里面?

git checkout不同分支时&#xff0c;为啥会把当前分支的修改内容也带到新分支里面&#xff1f; 当你在Git中从一个分支切换到另一个分支时&#xff0c;如果没有先将当前分支未提交的改动暂存或提交&#xff0c;这些改动会被带到新分支。这是因为Git的工作目录是共享的&#xf…

http发送post请求,发送参数为实体

public static String post(JSONObject json, String url) { String result “”; HttpPost post new HttpPost(url); try { CloseableHttpClient httpClient HttpClients.createDefault(); post.setHeader(“Content-Type”, “application/json;charsetutf-8”); post.add…

【Python循环3/5】条件循环语句

目录 导入 条件循环 边界条件 while循环 死循环 while循环与for循环的区别 总结 知识图谱 导入 我们已经学习了如何利用for语句实现代码重复执行的循环结构。通过遍历列表&#xff0c;输出其中的每一个元素。 for循环就像是排队办事&#xff0c;一个个进入&#xff0c;轮…

轻松打造完美原型:9款在线工具推荐

早年&#xff0c;UI设计师选择的工具有限&#xff0c;功能相对单一&#xff0c;大多数在线原型设计工具都是国外的&#xff0c;语言和网络都增加了设计工作的负担。如今&#xff0c;国内外有许多在线原型设计工具&#xff0c;不仅可以在浏览器上使用&#xff0c;而且还具有团队…

专业无网设备如何远程运维?向日葵远程控制能源场景案例解析

清洁能源领域&#xff0c;拥有庞大的上下游产业链&#xff0c;涉及的相关工业设备门类多、技术覆盖全、行业应用广。在这一领域内&#xff0c;相关专业设备的供应商的核心竞争力除了本身产品的技术能力之外&#xff0c;服务也是重要的一环。 某企业作为致力于节能环保方向的气…

(学习日记)2024.03.18:UCOSIII第二十节:移植到STM32

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

炒股技巧一文通!在深圳开股票账户交易佣金手续费一般是多少?

股票操作技巧可以说是股票投资成功的关键&#xff0c;下面是一些常用的技巧&#xff1a; 1.合理设置止盈止损&#xff1a;止盈可以帮助你在股票价格到达一定水平时获得利润&#xff0c;而止损可以保护你的本金&#xff0c;避免亏损过多。 2.选对个股&#xff1a;选对个股是根…