day27/60重写(补充)

DAY 27 函数专题2:装饰器

ps:第一期day27对应5月16日

知识点回顾:

  1. 装饰器的思想:进一步复用
  2. 函数的装饰器写法
  3. 注意内部函数的返回值

作业:

编写一个装饰器 logger,在函数执行前后打印日志信息(如函数名、参数、返回值)

@logger
def multiply(a, b):return a * bmultiply(2, 3)  
# 输出:
# 开始执行函数 multiply,参数: (2, 3), {}
# 函数 multiply 执行完毕,返回值: 6

本期内容如果无法理解,可以参考如下视频教学

B站-装饰器的使用


豆包:

以下是用生活场景比喻解释装饰器相关知识点,帮你秒懂这个「代码魔术」:

1. 装饰器的思想:给函数「穿外套」的复用艺术

本质:在不修改原函数代码的前提下,给函数「添加额外功能」,就像给衣服缝上口袋、给蛋糕加奶油。
核心目的:避免重复写相似代码(比如多个函数都需要「日志记录」功能),实现代码复用。

 

比喻

 
  • 装饰器 = 礼物包装纸
    • 原函数 = 「礼物本身」(比如一本书)。
    • 装饰器 = 「包装纸 + 蝴蝶结」(给礼物增加「美观」功能)。
    • 关键规则:不能拆开礼物修改内容(不修改原函数代码),但可以在外面套包装。
 

生活场景举例

 
  • 原函数 read_book() 是「看书」,装饰器可以是「记录看书时间」的功能:

    python

    运行

    def 记录时间(原函数):  # 装饰器函数,参数是原函数def 包装函数():print("开始时间:2025-06-10 10:00")原函数()  # 调用原函数(看书)print("结束时间:2025-06-10 11:00")return 包装函数@记录时间  # 用装饰器包装函数
    def read_book():print("正在阅读《Python入门》")read_book()  # 调用时会自动触发装饰器的「记录时间」功能
    

    输出:

    plaintext

    开始时间:2025-06-10 10:00
    正在阅读《Python入门》
    结束时间:2025-06-10 11:00
    

2. 函数装饰器的写法:三步搭出「包装流水线」

写法模板(以 Python 为例)

 
  1. 定义装饰器函数:接收原函数作为参数。
  2. 定义内部包装函数:在原函数前后添加新功能。
  3. 返回包装函数:用 @装饰器名 语法糖应用到目标函数。
 

比喻拆解:包装礼物的流水线

 

python

运行

# 1. 定义「包装纸」函数(装饰器)
def 包装纸(礼物):  # 礼物=原函数# 2. 定义「包装过程」函数(内部函数)def 包礼物():print("✨ 放上丝带")       # 新增功能1礼物()                   # 调用原礼物(不修改原内容)print("🎀 贴上祝福卡片")  # 新增功能2# 3. 返回「包装好的礼物」return 包礼物# 用装饰器包装「送书」函数
@包装纸  # 等价于 send_book = 包装纸(send_book)
def send_book():print("📚 送出《Python书》")# 调用包装后的函数
send_book()
 

执行效果

 

plaintext

✨ 放上丝带
📚 送出《Python书》
🎀 贴上祝福卡片

3. 注意内部函数的返回值:别让礼物「消失在包装里」

常见错误:如果内部函数不返回原函数的结果,原函数的返回值会丢失(就像把礼物放进盒子却不装进去,最后送出空盒子)。

 

比喻对比

 
  • 正确做法:包装礼物时必须把「礼物本身」放进盒子,否则收礼人拿到的是空盒子。
  • 错误做法:包装时只放包装纸,没放礼物,结果丢失了礼物。
 

代码示例

 

python

运行

# ❌ 错误写法:内部函数不返回原函数结果
def 错误装饰器(原函数):def 包装函数():print("开始装饰")原函数()  # 调用原函数,但没保存结果print("装饰结束")return 包装函数@错误装饰器
def get_gift():return "钻石戒指"  # 原函数返回一个值result = get_gift()
print(result)  # 输出:None(原函数的返回值丢失了!)# ✅ 正确写法:必须返回原函数的调用结果
def 正确装饰器(原函数):def 包装函数():print("开始装饰")gift = 原函数()  # 保存原函数的返回值print("装饰结束")return gift  # 返回原函数的结果return 包装函数@正确装饰器
def get_gift():return "钻石戒指"result = get_gift()
print(result)  # 输出:钻石戒指(结果正确传递)

终极比喻总结:装饰器是「函数的变装皇后」

装饰器要素生活比喻核心作用
原函数素颜的人原本的功能主体
装饰器函数造型师负责给函数「化妆」(添加功能)
内部包装函数化妆过程在原功能前后插入新操作
@装饰器语法造型师的「魔法咒语」一键应用变装效果
必须返回原结果化妆不能改变人的本质装饰后必须保留原函数的返回值
 

通过「包装礼物」的比喻,可以直观理解装饰器的「无侵入式增强」特性 —— 就像我们不会为了系蝴蝶结而拆开礼物盒,装饰器也不会修改原函数的代码,却能让函数「穿上新功能的外衣」,实现高效复用~ 🎁

另回答:

好的!我会用生活中的例子来比喻这三个知识点,尽量让抽象的概念变得直观~

1. 装饰器的思想:进一步复用

知识点解释
装饰器是一种不修改原有函数代码,却能为其动态添加新功能的编程技巧。它的核心是 “复用代码逻辑”,比如给多个函数统一添加日志记录、权限校验等功能,避免重复写重复代码。

比喻
就像给蛋糕加装饰:

  • 蛋糕本身(原有函数)的配方(代码)不需要改变,
  • 但可以通过裱花(装饰器)给不同蛋糕(不同函数)加上奶油、水果(新功能),
  • 而且同一套裱花工具(装饰器逻辑)可以重复用在多个蛋糕上,避免每次都重新设计装饰。

场景举例
比如多个函数都需要记录执行时间,用装饰器就像给每个函数 “贴” 一个计时器,不用每个函数里都写一遍计时代码。

2. 函数的装饰器写法

知识点解释
装饰器本质是一个高阶函数(参数或返回值是函数的函数),写法分两步:

  1. 定义装饰器函数:它接受一个函数(被装饰的函数)作为参数,返回一个内部函数(包裹了原函数的新功能)。
  2. @装饰器名语法糖给目标函数 “装饰”。

比喻
就像做三明治:

  • 面包片 1(装饰器外层函数):接受食材(原函数)作为参数,
  • 夹心菜肉(内部函数):在食材前后添加面包片(新功能),比如先抹酱(前置逻辑),再放食材(原函数执行),最后盖另一片面包(后置逻辑),
  • 成品三明治(返回的内部函数):比原来的食材更丰富,但保留了食材本身的味道(原函数功能)。

代码示例

python

# 定义装饰器:给函数加“吃前洗手”和“吃完擦嘴”的逻辑
def sandwich_decorator(func):def wrapper():  # 内部函数,包裹原函数print("✨ 先洗手(前置逻辑)")func()       # 执行原函数(吃三明治)print("✨ 再擦嘴(后置逻辑)")return wrapper   # 返回包裹后的函数# 用@语法糖装饰目标函数
@sandwich_decorator
def eat_sandwich():print("🍔 正在吃三明治(原函数逻辑)")# 调用装饰后的函数
eat_sandwich()

输出

plaintext

✨ 先洗手(前置逻辑)
🍔 正在吃三明治(原函数逻辑)
✨ 再擦嘴(后置逻辑)

3. 注意内部函数的返回值

知识点解释
如果原函数有返回值(比如计算结果),装饰器的内部函数必须显式返回原函数的调用结果,否则调用装饰后的函数会得到None(空值)。

比喻
就像送快递:

  • 原函数是 “打包商品” 的函数,返回值是 “包裹里的商品”,
  • 装饰器是 “贴快递单” 的流程,如果贴单后不把包裹(返回值)交给快递员(调用者),买家收到的就是空包裹(None)。

代码示例

python

# 错误示范:内部函数不返回原函数结果
def bad_decorator(func):def wrapper():func()  # 执行原函数,但不返回结果return wrapper@bad_decorator
def add(a, b):return a + b  # 原函数有返回值result = add(1, 2)
print(result)  # 输出:None(丢失了返回值!)

python

# 正确示范:内部函数返回原函数结果
def good_decorator(func):def wrapper(*args, **kwargs):  # 通用参数接收return func(*args, **kwargs)  # 必须返回原函数调用结果return wrapper@good_decorator
def add(a, b):return a + bresult = add(1, 2)
print(result)  # 输出:3(正确保留返回值)

总结

  • 装饰器思想:像给函数 “穿外套”,复用功能代码,不修改原函数。
  • 写法关键:装饰器是高阶函数,用@语法糖简化调用,内部函数包裹原函数。
  • 返回值注意:内部函数必须 “接住” 原函数的返回值并返回,否则结果会 “丢失”。

如果还有疑问,可以随时问我哦! 😊


代码:

def logger(func):def wrapper(*args, **kwargs):print(f"调用函数: {func.__name__},参数: {args}, {kwargs}")result = func(*args, **kwargs)print(f"函数返回值: {result}")return resultreturn wrapper
@logger
def multiply(a, b):return a * b multiply(2, 3)

 另代码:

def logger(func):def wrapper(*args, **kwargs):# 打印函数执行前的日志print(f"开始执行函数: {func.__name__}")print(f"位置参数: {args}")print(f"关键字参数: {kwargs}")# 执行原函数result = func(*args, **kwargs)# 打印函数执行后的日志print(f"函数 {func.__name__} 执行完毕")print(f"返回值: {result}")return resultreturn wrapper# 示例函数,用于测试装饰器
@logger
def add_numbers(a, b):return a + b# 调用示例函数
add_numbers(3, 5)

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

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

相关文章

网传西门子12亿美元收购云原生工业软件,云化PLM系统转机在协同

近日,网传西门子将以12亿美元全现金交易收购云原生MES公司FlexFact,并整合其技术至Xcelerator工业软件平台。如果此次收购动作完成,将会成为西门子加速工业云转型的标志性动作,背后的意义也极为深远,不仅会直接响应竞争…

大模型笔记_检索增强生成(RAG)

1. RAG的概念 RAG(Retrieval-Augmented Generation) 是一种结合 信息检索(Retrieval)与文本生成(Generation)的模型架构,旨在通过动态引入外部知识库或实时数据,提升大语言模型&…

Spring Security是如何完成身份认证的?

1. 用户名和密码被过滤器获取到,封装成 Authentication ,通常情况下是 UsernamePasswordAuthenticationToken 这个实现类。 2. AuthenticationManager 身份管理器负责验证这个 Authentication 3. 认证成功后, AuthenticationManager 身份管理器返回一…

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

1. 引言 1.1 研究背景与意义 气象数据是环境研究、农业生产、城市规划等领域的重要基础。随着互联网技术的发展,越来越多的气象数据以 XML 格式在网络上公开。XML(可扩展标记语言)因其结构化和自描述性的特点,成为数据交换的标准格式之一。然而,这些数据通常分散在不同的…

中小企业无线局域网络搭建与优化指南

1. 引言:无线网络——驱动中国中小企业数字化转型的引擎 无线网络已成为现代企业运营的基础设施,直接影响员工工作效率和客户体验。随着Wi-Fi7技术的成熟和普及,中小企业网络建设正迎来全新机遇。在数字经济浪潮席卷全球的今天,无…

【已解决】python的kafka-python包连接kafka报认证失败

先说原因:安装python包的时候,多装了一个kafka的包:kafka 1.3.5 我把py文件打包成二进制文件,在linux上执行就一直报认证失败,后来确认登录信息、认证方式没有问题,把这个kafka包卸载…

传输层协议TCP(下)

上一篇https://blog.csdn.net/Small_entreprene/article/details/148193741?sharetypeblogdetail&sharerId148193741&sharereferPC&sharesourceSmall_entreprene&sharefrommp_from_link 接下来,我们来谈论TCP具体的机制! 具体TCP机制 …

洛谷B3612 【深进1.例1】求区间和

题目描述 给定 n 个正整数组成的数列 a1​,a2​,⋯,an​ 和 m 个区间 [li​,ri​],分别求这 m 个区间的区间和。 输入格式 第一行,为一个正整数 n 。 第二行,为 n 个正整数 a1​,a2​,⋯,an​ 第三行,为一个正整数 m 。 接下…

debian12 修改MariaDB数据库存储位置报错

debian12 修改MariaDB数据库存储位置到home报错 MariaDB 修改存储路径后启动失败问题解决 更改数据存储位置 如果需要将数据存储到其他位置(如更大的分区): 停止 MariaDB 服务: bash sudo systemctl stop mariadb 创建新目录并设…

【评测】flux-dev文生图模型初体验

回到目录 【评测】flux-dev文生图模型初体验 1. 安装基础环境 参考 modelscope的Flux.1-dev页面 2. 使用tongyi写提示词 帮我用英文写3个,文生图片1024*1024的提示词,准备用flux.dev生成用 [pic03] 3. 运行代码 4090D满载运行, 1min左…

PHP7+MySQL5.6 雪里开简易预约制访客管理系统V1.0

# PHP7MySQL5.6 雪里开简易预约制访客管理系统 V1.0 ## 简介 本系统是一个基于PHP7和MySQL5.6的封闭校区访客管理系统,用于管理学生访客的申请、核销流程。 导入的账号预先提交访客信息(预约制),无需审核,访客提交匿名制访客码给门卫登记放行…

【深度学习:进阶篇】--2.4.BN与神经网络调优

学习目标 目标 知道常用的一些神经网络超参数知道BN层的意义以及数学原理 应用 无 目录 学习目标 1.神经网络调优 1.1.调参技巧 1.2.运行 2.批标准化(Batch Normalization) 2.1.标准化公式 2.2.为什么可以优化简单 2.3.BN总结 1.神经网络调优 …

CMake指令: add_sub_directory以及工作流程

目录 1.简介 2.工作流程 3.示例场景 4.最佳实践 5.注意事项 6.总结 相关链接 1.简介 add_subdirectory 是 CMake 中用于添加子目录参与构建的命令,允许将项目拆分为多个模块或子项目,实现代码的模块化管理。 基本语法: add_subdirect…

【C++ 】智能指针:内存管理的 “自动导航仪”

目录 一、引入 二、智能指针的两大特性: 1、RAII 特点: 好处: 2、行为像指针 三、智能指针起初的缺陷:拷贝问题 四、几种智能指针的介绍。 1、C98出现的智能指针——auto_ptr auto_ptr解决上述拷贝构造的问题&#xff1a…

Java多线程实现之线程池详解

Java多线程实现之线程池详解 一、线程池的基本概念1.1 为什么需要线程池1.2 线程池的核心思想 二、Java线程池的实现2.1 Executor框架2.2 ThreadPoolExecutor构造参数 三、常见线程池类型3.1 FixedThreadPool3.2 CachedThreadPool3.3 SingleThreadExecutor3.4 ScheduledThreadP…

解码美元-黄金负相关:LSTM-Attention因果发现与黄金反弹推演

摘要:本文采用时间序列分析框架与自然语言处理(NLP)技术,对黄金与美元指数的负相关关系进行量化拆解。通过构建包含宏观经济因子、市场情绪指标及地缘风险的三维分析模型,揭示当前贵金属市场的核心驱动逻辑&#xff0c…

Asp.Net Core SignalR导入数据

文章目录 前言一、安装包二、使用步骤1.实现SignalR Hub服务:2.实现CSV文件解析及数据导入服务3.控制器4.前端实现(vue) 三、关键技术点说明总结 前言 导入CSV文件中的数据到数据库,使用CsvHelper解析CSV文件,SqlBulk…

Modern C++(四)声明

4、声明 声明是将名字引入到cpp程序中,不是每条声明都声明实际的东西。定义是足以使该名字所标识的实体被使用的声明。声明包含以下几种: 函数定义模板声明模板显式实例化模板显式特化命名空间定义链接说明属性声明(C11)空声明&…

目标检测yolo算法

yolov5s: 从github官网下载yolov5的算法之后,配置好环境(pycharm安装包-CSDN博客),再下载权重文件,比如默认的yolov5s.pt; 运行当前文件(detect.py),就能看…

一个超强的推理增强大模型,开源了,本地部署

大家好,我是 Ai 学习的老章 前几天介绍了MOE 模型先驱 Mistral 开源的代码 Agent 大模型——mistralai/Devstral-Small-2505 今天一起看看 Mistral 最新开源的推理大模型——Magistral Magistral 简介 Mistral 公司推出了首个推理模型 Magistral 及自研可扩展强…