解析Python装饰器高级用法6项

server/2025/2/6 4:21:31/

在Python编程中,装饰器(Decorators)是一种强大且灵活的工具,它允许你在不修改原有函数或方法定义的情况下,为其添加新的功能。装饰器是高级主题,但掌握它后,你将能写出更加简洁和可重用的代码。本文将深入探讨Python装饰器的6项高级用法,通过详细的例子和逐步的引导,帮助初学者理解和掌握这一强大特性。

1. 带参数的装饰器

装饰器本身也可以接受参数,这使得装饰器更加灵活。我们可以通过定义一个外层的函数来传递参数给装饰器。

def my_decorator(arg):    def wrapper(func):    def inner(*args, **kwargs):    print(f"Decorator argument: {arg}")    return func(*args, **kwargs)    return inner    return wrapper    @my_decorator("Hello, World!")    
def say_hello():    print("Hello from the function!")    say_hello()  

输出

Decorator argument: Hello, World!    
Hello from the function!  

代码解释

  • my_decorator 是一个接受参数的装饰器工厂。
  • wrapper 是实际的装饰器,它接受一个函数 func 作为参数。
  • inner 是实际调用原始函数并添加额外功能的包装函数。

2. 类装饰器

除了函数装饰器,Python还支持类装饰器。类装饰器允许你使用类来定义装饰器逻辑。

class MyDecorator:    def __init__(self, func):    self.func = func    def __call__(self, *args, **kwargs):    print("Before the function is called.")    result = self.func(*args, **kwargs)    print("After the function is called.")    return result    @MyDecorator    
def greet(name):    print(f"Hello, {name}!")    greet("Alice")  

输出

Before the function is called.    
Hello, Alice!    
After the function is called.  

代码解释

  • MyDecorator 是一个类,它的 __init__ 方法接受一个函数 func
  • __call__ 方法使得类的实例可以像函数一样被调用。

3. 装饰器链

你可以将多个装饰器应用于同一个函数,这些装饰器会按照从外到内的顺序被调用。

def decorator_one(func):    def wrapper(*args, **kwargs):    print("Decorator One")    return func(*args, **kwargs)    return wrapper    def decorator_two(func):    def wrapper(*args, **kwargs):    print("Decorator Two")    return func(*args, **kwargs)    return wrapper    @decorator_one    
@decorator_two    
def my_function():    print("My Function")    my_function()  

输出

Decorator One    
Decorator Two    
My Function    

代码解释

  • decorator_onedecorator_two 是两个装饰器。
  • @decorator_one@decorator_two 按照从外到内的顺序应用于 my_function

4. 装饰器中的装饰器

装饰器内部也可以嵌套使用其他装饰器,从而组合多个装饰器的功能。

def decorator_a(func):    def wrapper(*args, **kwargs):    print("Decorator A")    return func(*args, **kwargs)    return wrapper    def decorator_b(func):    def wrapper(*args, **kwargs):    print("Decorator B")    return func(*args, **kwargs)    return wrapper    def combine_decorators(func):    return decorator_a(decorator_b(func))    @combine_decorators    
def my_function():    print("My Function")    my_function()  

输出

Decorator A    
Decorator B    
My Function  

代码解释

  • combine_decorators 是一个装饰器,它将 decorator_adecorator_b 组合在一起。

5. 装饰器与异步函数

Python 3.5 引入了异步编程的支持,装饰器也可以用于异步函数。

import asyncio    def async_decorator(func):    async def wrapper(*args, **kwargs):    print("Before the async function is called.")    await func(*args, **kwargs)    print("After the async function is called.")    return wrapper    @async_decorator    
async def async_greet(name):    await asyncio.sleep(1)    print(f"Hello, {name}!")    async def main():    await async_greet("Bob")    asyncio.run(main())  

输出

Before the async function is called.    
Hello, Bob!    
After the async function is called.  

代码解释

  • async_decorator 是一个装饰器,用于异步函数。
  • async_greet 是一个异步函数,通过 await 关键字等待异步操作完成。

6. 装饰器与属性

在类的方法上应用装饰器时,可以访问类的属性和其他方法。

class MyClass:    def __init__(self):    self.count = 0    def decorator(self, func):    def wrapper(*args, **kwargs):    self.count += 1    print(f"Count before call: {self.count}")    result = func(*args, **kwargs)    print(f"Count after call: {self.count}")    return result    return wrapper    @decorator    def my_method(self):    print("Method is called")    obj = MyClass()    
obj.my_method()    
obj.my_method()  

输出

Count before call: 1    
Method is called    
Count after call: 2    
Count before call: 3    
Method is called    
Count after call: 4    

代码解释

  • MyClass 类中有一个装饰器 decorator,它访问类的 count 属性。
  • @decorator 应用于 my_method,每次调用 my_method 时都会更新 count 属性。

实战案例:日志记录装饰器

在实际开发中,日志记录是一个常见的需求。我们可以编写一个装饰器来自动记录函数的调用情况,包括调用时间、参数和返回值。

import time    def log_decorator(func):    def wrapper(*args, **kwargs):    start_time = time.time()    print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")    result = func(*args, **kwargs)    end_time = time.time()    print(f"{func.__name__} returned {result} in {end_time - start_time:.4f} seconds")    return result    return wrapper    @log_decorator    
def complex_calculation(a, b):    time.sleep(2)  # Simulate a long-running calculation    return a + b    result = complex_calculation(3, 4)    
print(f"Final result: {result}")  

输出

Calling complex_calculation with args: (3, 4), kwargs: {}    
complex_calculation returned 7 in 2.0021 seconds    
Final result: 7    

案例分析

  • log_decorator 装饰器记录了 complex_calculation 函数的调用时间、参数和返回值。
    - 这种方式非常适用于调试和性能分析,而不需要修改原始函数的代码。

总结

本文通过6个高级用法详细探讨了Python装饰器的强大功能,包括带参数的装饰器、类装饰器、装饰器链、装饰器中的装饰器、装饰器与异步函数以及装饰器与属性的结合使用。通过实际的代码示例和逐步引导,希望读者能够深入理解装饰器的原理和应用。


http://www.ppmy.cn/server/165323.html

相关文章

UE编辑器工具

如何自己制作UE小工具提高工作效率 在虚幻编辑器用户界面中,可以使用各种各样的可视化工具来设置项目,设计和构建关卡,创建游戏性交互等等。但有些时候,当你确定了需要编辑器执行的操作后,可能想要通过编程方式调用它…

【实战篇】Android安卓本地离线实现视频检测人脸

实战篇Android安卓本地离线实现视频检测人脸 引言项目概述核心代码类介绍人脸检测流程项目地址总结 引言 在当今数字化时代,人脸识别技术已经广泛应用于各个领域,如安防监控、门禁系统、移动支付等。本文将以第三视角详细讲解如何基于bifan-wei-Face/De…

win32汇编环境,对话框程序生成选项卡(属性页\标签)控件及运用

;运行效果 ;win32汇编环境,对话框程序生成选项卡(属性页\标签)控件及运用 ;主要是生成1个选项卡,同时准备好几个对话框,然后将对话框叠加到选项卡控件里面,在运行时点击哪一项时则显示对应的对话框。 ;以下示例显示3个项的选项卡控件 ;直接抄进RadAsm可编译运行。重要部分加…

100 ,【8】 buuctf web [蓝帽杯 2021]One Pointer PHP(别看)

进入靶场 没提示&#xff0c;去看源代码。 user.php <?php // 定义一个名为 User 的类&#xff0c;该类可用于表示用户相关信息或执行与用户有关的操作 class User{// 声明一个公共属性 $count&#xff0c;可在类的内部和外部直接访问// 这个属性可能用于记录与用户相关…

【毕业与课程大作业参考】基于 yolov8+pyqt5 界面自适应的表情识别检测系统 demo

【毕业与课程大作业参考】基于yolov8pyqt5界面自适应的表情识别检测系统demo.zip资源-CSDN文库 【毕业与课程大作业参考】基于 yolov8pyqt5 界面自适应的表情识别检测系统 demo 在人工智能和计算机视觉领域&#xff0c;表情识别检测系统是一个极具趣味性和挑战性的项目。对于正…

实施工程师:面试基础宝典

一.运维工程师和实施工程师的区别&#xff1a;工作内容不同、职能不同、工作形式不同 1.工作内容不同&#xff1a; 运维工程师要对公司硬件和软件进行维护。 硬件包括&#xff1a;机房、机柜、网线光纤、PDU、服 务器、网络设备、安全设备等。 实施工程师包括常用操作系统、应…

Python | Pytorch | Tensor知识点总结

如是我闻&#xff1a; Tensor 是我们接触Pytorch了解到的第一个概念&#xff0c;这里是一个关于 PyTorch Tensor 主题的知识点总结&#xff0c;涵盖了 Tensor 的基本概念、创建方式、运算操作、梯度计算和 GPU 加速等内容。 1. Tensor 基本概念 Tensor 是 PyTorch 的核心数据结…

基于直觉的理性思维入口:相提并论的三者 以“网络”为例

以下主要是 腾讯云 AI 代码助手的答问。 Q1、假设有且只有一个 能和主干网和 骨干网 相提并论的其它什么 “**网”&#xff0c;您觉得应该是什么 在考虑能与主干网和骨干网相提并论的“网”时&#xff0c;我们需要思考哪些网络在规模、重要性或功能上与这两者相当。主干网和骨…