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

DAY 27 函数专题2:装饰器-2025.9.14

函数专题2:装饰器

知识点回顾

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

作业

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

笔记:

装饰器是 Python 中一种非常强大的代码复用机制,核心思想是 “在不修改原函数代码的前提下,为函数添加额外功能”。它就像给函数 “戴帽子”—— 帽子(装饰器)提供额外功能,而函数本身的逻辑保持不变。这种思想在实际开发中(比如日志记录、性能计时、权限校验等场景)非常实用。

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

假设你有 10 个函数,现在需要给每个函数添加 “执行前打印开始信息,执行后打印结束信息” 的功能。如果逐个修改这 10 个函数,会产生大量重复代码。

装饰器的解决方案是:** 把这些重复的 “增强功能” 写成一个通用的装饰器,然后 “套” 在需要增强的函数上 **。这样既不用修改原函数,又能实现功能复用。

核心逻辑:

  • 装饰器本身是一个函数(或类)
  • 接收 “被装饰的函数” 作为参数
  • 返回一个 “增强后的新函数”
  • 新函数会调用原函数,并在调用前后添加额外逻辑

2. 函数的装饰器写法

装饰器的基本结构是嵌套函数(函数内部定义另一个函数),外层函数负责接收原函数,内层函数负责实现增强逻辑并调用原函数,最后外层函数返回内层函数。

基础示例:定义一个打印函数执行日志的装饰器

# 定义装饰器(外层函数)
def log_decorator(func):# 定义内层函数(增强后的函数)def wrapper():print(f"开始执行函数:{func.__name__}")  # 额外功能:执行前打印func()  # 调用原函数print(f"函数{func.__name__}执行结束\n")  # 额外功能:执行后打印return wrapper  # 返回内层函数# 使用装饰器:用@符号把装饰器“套”在函数上
@log_decorator
def add():print("执行加法运算...")@log_decorator
def multiply():print("执行乘法运算...")# 调用被装饰后的函数
add()
multiply()

关键语法

  • @log_decorator 等价于 add = log_decorator(add),即把原函数传给装饰器,再用返回的新函数覆盖原函数名。
  • 装饰器会在函数定义时就生效,而不是调用时。

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

如果被装饰的函数有返回值,装饰器的内层函数必须将原函数的返回值传递出去,否则会丢失返回值(默认返回None)

示例:处理带返回值的函数

def log_decorator(func):def wrapper():print(f"开始执行{func.__name__}...")result = func()  # 保存原函数的返回值print(f"{func.__name__}执行结束")return result  # 传递返回值return wrapper@log_decorator
def calculate_sum():return 1 + 2  # 原函数有返回值# 调用函数
total = calculate_sum()
print(f"计算结果:{total}")  # 如果wrapper不返回result,这里会打印None

为什么必须传递返回值?

内层函数wrapper是最终被调用的函数,如果wrapper不返回func()的结果,那么调用calculate_sum()时,实际得到的是wrapper()的返回值(默认None),原函数的返回值就会丢失。

进阶:装饰带参数的函数

如果被装饰的函数有参数,内层函数wrapper需要用*args**kwargs接收任意参数,并传递给原函数。

def log_decorator(func):# 用*args和**kwargs接收任意参数def wrapper(*args, **kwargs):print(f"开始执行{func.__name__},参数:{args}, {kwargs}")result = func(*args, **kwargs)  # 传递参数给原函数print(f"{func.__name__}执行结束")return resultreturn wrapper@log_decorator
def add(a, b):return a + b@log_decorator
def greet(name, message="Hello"):return f"{message}, {name}!"print(add(3, 5))
print(greet("Alice", message="Hi"))

总结

  1. ** 装饰器思想: 不修改原函数代码,通过 “包装” 增强函数功能,实现代码复用。
  2. 基本写法 :嵌套函数(外层接收原函数,内层实现增强逻辑并返回),用@装饰器名简化调用。
  3. 内部函数返回值 **:必须返回原函数的执行结果(return func(...)),否则会丢失返回值。

装饰器在实际开发中应用广泛,比如:

  • 日志记录(记录函数调用参数和结果)
  • 性能计时(计算函数执行时间)
  • 权限校验(调用函数前检查用户权限)
  • 异常捕获(自动处理函数可能抛出的异常)

作业

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

@loggerdef multiply(a, b):return a * bmultiply(2, 3)  

输出:

开始执行函数 multiply,参数: (2, 3), {}

函数 multiply 执行完毕,返回值: 6


def logger(func):def wrapper(*args,**kwargs):print(f'开始执行函数{func.__name__},参数:{args},{kwargs}')result = func(*args,**kwargs)print(f'函数{func.__name__}执行完毕,返回值:{result}')return resultreturn wrapper@logger
def multiply(a, b):return a * bmultiply(2, 3)

开始执行函数multiply,参数:(2, 3),{}
函数multiply执行完毕,返回值:6

@浙大疏锦行


文章转载自:

http://y9qySUkr.bpmnz.cn
http://uEQNwYxL.bpmnz.cn
http://aOErzuer.bpmnz.cn
http://FhGCMdsa.bpmnz.cn
http://LKChQkvA.bpmnz.cn
http://6A68yjX6.bpmnz.cn
http://kTuYChUe.bpmnz.cn
http://22TsmNBm.bpmnz.cn
http://kfZ5HO3Z.bpmnz.cn
http://dKcE4PbX.bpmnz.cn
http://BIDYSQNn.bpmnz.cn
http://CLI489aU.bpmnz.cn
http://Czq7qpgM.bpmnz.cn
http://li4VjeXB.bpmnz.cn
http://CDILmiWX.bpmnz.cn
http://poXFBfYh.bpmnz.cn
http://yD6KIKVC.bpmnz.cn
http://nik805Ah.bpmnz.cn
http://WOW0e5nf.bpmnz.cn
http://h9Swqk32.bpmnz.cn
http://eTRS1Qvr.bpmnz.cn
http://jeaSHQrv.bpmnz.cn
http://kH9fcsXQ.bpmnz.cn
http://qj766boO.bpmnz.cn
http://9s43fNc1.bpmnz.cn
http://lQY1II9J.bpmnz.cn
http://UDlNd7Bc.bpmnz.cn
http://q8wLQZq0.bpmnz.cn
http://VfMUemeo.bpmnz.cn
http://4XRxMmS4.bpmnz.cn
http://www.dtcms.com/a/382132.html

相关文章:

  • 浅析Linux进程信号处理机制:基本原理及应用
  • php学习(第五天)
  • C盘清理技巧分享的技术文章大纲
  • PINN物理信息神经网络驱动的三维声波波动方程求解MATLAB代码
  • 深度学习优化器进化史:从SGD到AdamW的原理与选择
  • 计算机视觉(opencv)实战十九——角点检测图像特征(Harris 角点、Shi-Tomasi 角点)
  • 【限流器设计】固定窗口计数法
  • Estimator and Confidence interval
  • 构建AI智能体:三十二、LangChain智能体:打造会使用工具(Tools)、有记忆(Memory)的AI助手
  • AI内容标识新规实施后,大厂AI用户协议有何变化?(六)科大讯飞
  • 机械应答到自然交流,声网AI陪练改变我的口语
  • 贪心算法应用:信用评分分箱问题详解
  • 【Spring AI】Filter 简单使用
  • html各种常用标签
  • Linux 进程信号之信号的捕捉
  • 实验-高级acl(简单)
  • C++之特殊类设计
  • stm32教程:USART串口通信
  • 地级市绿色创新、碳排放与环境规制数据
  • ES——(二)基本语法
  • 中级统计师-统计法规-第十一章 统计法律责任
  • 拥抱直觉与创造力:走进VibeCoding的新世界
  • Python进程和线程——多进程
  • 论文阅读 2025-9-13 论文阅读随心记
  • leecode56 合并区间
  • 用R获取 芯片探针与基因的对应关关系 bioconductor的包的 三者对应关系
  • xxl-job的使用
  • 2025 年 9 月 12 日科技前沿动态全览
  • 高德地图自定义 Marker:点击 悬停 显示信息框InfoWindow实战(Vue + AMap 2.0)
  • 猿辅导Java后台开发面试题及参考答案