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

装饰器

10. 装饰器

大家能够认识装饰器即可。不会定义的话,目前影响不大,以后工作遇到了再深入学习

10.1. 装饰器的概念

装饰器是Python中的一个强大特性,它本质上是一个函数,用于在不修改被装饰函数源代码和调用方式的情况下,对函数的功能进行扩展或修改。可以把装饰器想象成一个包装器,它将被装饰的函数包裹起来,在函数执行前后添加一些额外的逻辑。

10.2. 装饰器的基本语法

装饰器的基本语法是使用 @ 符号加上装饰器函数的名称,放在被装饰函数的定义之前。

# func代表被装饰的函数,
# 装饰器更准确的描述是一个嵌套函数,且将内函数返回出
def decorator_function(func):# func:代表就是被装饰的函数def wrapper_function():print("在函数执行之前做一些事情")func()  # 调用被装饰的函数print("在函数执行之后做一些事情")# 返回内函数本身,不要有()return wrapper_function# 使用装饰器
@decorator_function
def my_function():print("这是原函数的功能")# 调用my_function函数后,检查到my_function函数有装饰器,
# 所以会先调用装饰器,然后调用被装饰的函数
my_function()

在上述示例中:decorator_function 是一个装饰器函数,它接受一个函数作为参数(这里是 func)。在 decorator_function 内部,定义了一个新的函数 wrapper_function,这个函数在执行被装饰函数 func 之前和之后分别添加了一些额外的逻辑(这里是打印一些信息)。然后通过 return wrapper_function 返回了这个包装后的函数。最后,使用 @decorator_function 将 decorator_function 应用到 my_function 上,使得 my_function 在被调用时,实际上执行的是经过装饰后的 wrapper_function。当调用 my_function() 时,输出结果如下:

在函数执行之前做一些事情
这是原函数的功能
在函数执行之后做一些事情

10.3. 装饰器的参数传递

如果被装饰函数本身带有参数,那么装饰器函数中的包装函数也需要能够接收这些参数,以便正确地传递给被装饰函数。

# 函数的装饰器
def add_decorator(func):# wrapper是常用的装饰器内函数的名称# *args:接收位置可变参数。# **kwargs:接收关键字可变参数。def wrapper(*args, **kwargs):print("这是装饰器, wrapper11")# 将结果保存r = func(*args, **kwargs)print("这是装饰器, wrapper22")# 将结果返回return rreturn wrapper@add_decorator
def add_numbers(a, b):return a + b

在这个示例中:

  • 装饰器函数 decorator_function 中的 wrapper_function 使用了 *args**kwargs 来接收任意数量的位置参数和关键字参数,这样就可以正确地将参数传递给被装饰函数 my_function
  • 当调用 my_function(3, 5) 时,35 会通过 *args**kwargs 传递给 wrapper_function,然后再由 wrapper_function 传递给 my_function。输出结果如下:
    1 在函数执行之前做一些事情
    2 这是原函数的功能,计算 3 + 5 的和
    3 在函数执行之后做一些事情
    4 函数返回结果:8

    10.4. 多个装饰器的使用

    一个函数可以同时被多个装饰器装饰,此时装饰器的应用顺序是从下往上(即离被装饰函数定义最近的装饰器先应用),但执行顺序是从上往下(即最上面的装饰器对应的包装函数先执行)。

    def decorator1(func):def wrapper1():print("装饰器1:在函数执行之前做一些事情")func()print("装饰器1:在函数执行之后做一些事情")return wrapper1def decorator2(func):def wrapper2():print("装饰器2:在函数执行之前做一些事情")func()print("装饰器2:在函数执行之后做一些事情")return wrapper2@decorator1
    @decorator2
    def my_function():print("这是原函数的功能")my_function()

    在上述示例中:

    • 首先定义了两个装饰器 decorator1decorator2
    • 然后使用 @decorator1@decorator2 将这两个装饰器应用到 my_function 上,按照从下往上的顺序,先应用 decorator2,再应用 decorator1
    • 当调用 my_function() 时,执行顺序是从上往下,首先执行 decorator1 对应的 wrapper1 函数,在其内部会先执行 decorator2 对应的 wrapper2 函数,然后再执行原函数 my_function。输出结果如下:
      装饰器1:在函数执行之前做一些事情
      装饰器2:在函数执行之前做一些事情
      这是原函数的功能
      装饰器2:在函数执行之后做一些事情
      装饰器1:在函数执行之后做一些事情

      10.5. 带参数的装饰器

      有时候我们可能需要根据不同的条件或参数来定制装饰器的行为,这时就可以使用带参数的装饰器。带参数的装饰器实际上是一个返回装饰器函数的函数。

      # 三层嵌套函数来实现的œ
      def repeat(n, m): # m只是演示多个参数的使用,没有意义print("n", n, "m", m)def decorator_function(func):def wrapper_function(*args, **kwargs):for i in range(n):result = func(*args, **kwargs)return resultreturn wrapper_functionreturn decorator_function@repeat(4, "哈哈")
      def my_ddd():print("这是原函数的功能, ddd")my_ddd()

      在上述示例中:

      • repeat 是一个带参数的装饰器,它接受一个参数 n,用于指定要重复执行被装饰函数的次数。
      • repeat 内部定义了一个装饰器函数 decorator_function,这个函数又定义了一个包装函数 wrapper_function,在 wrapper_function 中会根据传入的 n 值重复执行被装饰函数 func
      • 当使用 @repeat(3) 将这个带参数的装饰器应用到 my_function 上时,意味着 my_function 将被重复执行3次。输出结果如下:
        1 这是原函数的功能
        2 这是原函数的功能
        3 这是原函数的功能

        10.6. 装饰器的应用场景

        • 日志记录:可以在函数执行前后记录相关信息,如函数名称、执行时间、输入参数和输出结果等,方便调试和监控程序运行情况。
        • 权限验证:在函数执行前验证用户是否具有执行该函数的权限,若没有权限则可以采取相应的措施,如抛出异常或返回错误提示。
        • 缓存机制:对于一些计算成本较高的函数,可以在装饰器中实现缓存机制,当函数再次被调用且输入参数相同时,直接从缓存中获取结果而无需重新计算,提高程序运行效率。

        通过以上介绍,你应该对Python装饰器有了较为全面的了解,它是一种非常有用的编程工具,可以在不修改原有函数代码的基础上,轻松实现多种功能扩展和优化。

        10.7. 作业

        • 写一个装饰器来计算函数执行时间
           1 import time
           2 
           3 
           4 def calculate_execution_time(func):
           5     def wrapper(*args, **kwargs):
           6         start_time = time.time()
           7         result = func(*args, **kwargs)
           8         end_time = time.time()
           9         execution_time = end_time - start_time
          10         print(f"{func.__name__} 函数执行时间: {execution_time} 秒")
          11         return result
          12     return wrapper

           

 
 
http://www.jsqmd.com/news/569620/

相关文章:

  • NCM音频格式转换完全指南:从加密限制到自由播放的技术突破
  • 鸿蒙 ArkTS 高级样式复用:@Extend 装饰器完全解析(比 @Styles 更强大)
  • 信息平权的技术突破:Bypass Paywalls Clean内容访问创新方案
  • 5步掌握QtScrcpy:安卓设备键鼠映射与屏幕控制完整方案
  • Qwen3.5-4B-Claude-Opus基础教程:llama.cpp后端参数与Web前端映射关系
  • 3步终结窗口混乱:AlwaysOnTop的空间管理效率革命
  • G-Helper电池管理工具:解决华硕笔记本续航衰减的完整方案
  • 火影迷的AI绘画神器:忍者绘卷Z-Image Turbo零基础入门实战
  • Anthropic 翻车了:51万行代码泄露,AI 巨头的底裤被扒了个干净
  • Hunyuan-MT-7B性能优化:Pixel Language Portal在多卡并行推理下的负载均衡部署教程
  • mPLUG视觉问答小白教程:3步实现本地图片智能分析
  • 解锁加密IP核:在Vivado中为FPGA网表构建与使用仿真模型的完整指南
  • OpenMetadata社区贡献实战:我是如何为它新增Doris连接器并成功合并PR的
  • 如何快速配置TranslucentTB:Windows任务栏美化终极教程
  • 超高压输电线路空载运行时的电压升高现象解析
  • 使用fetchEventSource构建高效AI智能助手:文件搜索场景的完整实现与深度解析
  • 别再死记公式了!用PyTorch的loss.backward()和optimizer.step()理解反向传播的‘自动挡’
  • 人工智能的拐点:从规模竞赛到智能效率
  • 如何实现格式保留翻译?Hunyuan MT1.5结构化文本处理实战解析
  • 开源工具DLSS Swapper效率提升指南:三步掌握配置技巧与性能优化
  • MT5工具集成指南:如何将文本增强API融入你的工作流
  • 2026年热门的多通道插回损测试仪/多波长检测插回损测试仪/极性一体检测插回损测试仪/光器件在线监控系统插回损测试仪精选厂家 - 品牌宣传支持者
  • ROS插件开发避坑实录:从global_planner插件注册失败到成功加载的完整排错流程
  • Phi-4-mini-reasoning案例展示:Chainlit前端实时显示思维链(CoT)生成过程
  • 智能电表DLMS协议入门避坑指南:从物理层到应用层的5个常见错误
  • ECharts进阶技巧:动态markLine(阈值线、警戒线)与箭头标记的实战应用
  • 智能体AI崛起:本体论如何赋能药物研发新纪元?——2026智能体年深度解析
  • Phi-4-mini-reasoning步骤详解:supervisorctl管理服务全命令解析
  • 如何在5分钟内掌握winget-install?开源命令行工具安装指南
  • 2026年靠谱的S砖/C70S砖源头工厂推荐 - 品牌宣传支持者