Python装饰器介绍与使用指南

文章目录

  • 前言——“装饰器”的解释
  • 一、装饰器应用的场景
  • 二、装饰器的种类
  • 三、使用装饰器的一般步骤:
  • 四、装饰器在 Python 中具有以下作用:
  • 五、装饰器命名规范
  • 装饰器名字可以随便取吗?

  • 前言——“装饰器”的解释

    装饰器是一种在不改变被装饰对象源代码的情况下,通过扩展或修改功能或行为的方法。它是 Python 中的一项强大功能,基于函数或类实现。


    一、装饰器应用的场景

    (1)函数装饰器:函数装饰器是一种用来包装函数的函数。它接受被装饰的函数作为输入,并返回一个新的函数或可调用对象,用于代替原始函数。函数装饰器可以在被装饰的函数执行前后添加额外的逻辑或行为,例如日志记录、性能计时等。

    (2)类装饰器:类装饰器是一种用来包装类的类。它接受被装饰的类作为输入,并返回一个新的类。类装饰器可以在被装饰的类的实例化或方法调用前后添加额外的逻辑或行为,例如权限验证、事件触发等。

    二、装饰器的种类

    Python 中有三种常见的装饰器类型:

    1. 函数装饰器:函数装饰器是最常见的一种装饰器类型。它允许我们在不改变原函数定义的情况下,对函数进行额外的功能扩展或修改。函数装饰器以一个函数作为输入,并返回一个修改后的函数作为输出。函数装饰器使用@ 符号将装饰器应用于函数,例如:
    @decorator
    def function():
        pass
    
    1. 类装饰器:类装饰器是应用于类定义的装饰器。它们可以修改类的行为、属性或方法。与函数装饰器类似,类装饰器以一个类作为输入,并返回一个修改后的类作为输出。类装饰器通常使用 @ 符号将装饰器应用于类,例如:
    @decorator
    class MyClass:
        pass
    
    1. 方法装饰器:方法装饰器是应用于类中方法的装饰器。它们允许我们在不改变原方法定义的情况下,对方法进行额外的功能扩展或修改。方法装饰器以一个方法作为输入,并返回一个修改后的方法作为输出。方法装饰器在类中直接应用于方法,例如:
    class MyClass:
        @decorator
        def my_method(self):
            pass
    

    值得注意的是,装饰器的本质是一个函数或类,它可以通过修改、包装或替换被装饰的函数或类来实现其功能。装饰器提供了一种灵活且优雅的方式来修改现有代码的行为,同时保持代码的简洁和可读性。

    三、使用装饰器的一般步骤:

    (1)定义装饰器函数或类:创建一个装饰器函数或类,用于定义装饰器的逻辑和行为。

  • 如果是函数装饰器,函数的第一个参数通常是被修饰的函数对象(可以带有其他参数),并返回一个新的函数。装饰器函数可以在内部包含额外的逻辑和功能。
  • 如果是类装饰器,类装饰器需要实现 initcall 方法。__init__方法在装饰器初始化时调用,call 方法在装饰器被调用时调用,并返回一个被包装的对象。
  • (2)应用装饰器:使用 @ 符号将装饰器应用到要修饰的函数或类上,即将装饰器放在要修饰的函数或类的定义之前。

  • 对于函数装饰器,可以将装饰器直接放在函数定义之前,例如 @decorator。
  • 对于类装饰器,可以将装饰器直接放在类定义之前,例如 @decorator。
  • 对于方法装饰器,可以将装饰器直接放在类中的方法定义之前,例如 @decorator。
  • (3)调用被装饰的对象:通过调用被装饰后的函数或类,来间接调用原始函数或类,并享受装饰器提供的功能扩展。
    例1:
    下面是一个简单的例子,演示如何使用装饰器:

    # 定义一个简单的装饰器函数
    def decorator(func):
        def wrapper(*args, **kwargs):
            print("执行装饰器逻辑")
            result = func(*args, **kwargs)  # 调用原函数
            result1 = result + ',I am a decorateor'
            return result1
        return wrapper
    
    # 应用装饰器到函数
    @decorator
    def greet(name):
        return f"Hello, {name}!"
    
    # 使用被装饰的函数
    message = greet("Alice")
    print(message)
    

    执行结果如下:

    执行装饰器逻辑
    Hello, Alice!,I am a decorateor

    例2:
    下面是一个简单的示例,演示如何使用函数装饰器来添加日志记录功能

    def log_decorator(func):
        def wrapper(*args, **kwargs):
            print(f"调用函数 {func.__name__},参数:{args}, {kwargs}")
            result = func(*args, **kwargs)
            print(f"函数 {func.__name__} 执行完毕,结果:{result}")
            return result
        return wrapper
    
    @log_decorator
    def add(a, b):
        return a + b
    
    result = add(3, 5)
    print(result)
    

    执行结果如下:

    调用函数 add,参数:(3, 5), {}
    函数 add 执行完毕,结果:8
    8

    在上面的示例中,log_decorator 是一个装饰器函数,它会在被装饰函数 add 执行前后分别打印日志信息。通过在 add 函数定义之前添加 @log_decorator,将 log_decorator 装饰器应用到 add 函数上。当调用 add(3, 5) 时,实际上是调用了被装饰后的函数 wrapper,并输出了日志信息,最终返回结果为 8。

    这样,我们通过装饰器实现了对 add 函数的日志记录功能,而不需要修改 add 函数的源代码。
    当然,装饰器除了有日志记录功能外,还有其他作用,下面将介绍:“装饰器在 Python 中的作用”

    四、装饰器在 Python 中具有以下作用:

    (1)扩展功能:装饰器可以在不修改被修饰函数或类的情况下,为其添加额外的功能或行为。通过在装饰器中包装原始函数或类,可以在执行前后执行一些预处理或后处理操作。

    (2)代码复用:装饰器可以将一些常用的功能或逻辑封装成装饰器,然后在多个函数或类中重复使用。这样可以减少代码重复,提高代码的可维护性。

    (3)日志记录:通过使用装饰器,可以方便地记录函数或类的调用日志。装饰器可以在函数或类的调用前后打印日志信息,以帮助调试和追踪程序的执行流程。

    (4)输入验证:装饰器可以用于验证函数或类的输入参数。通过在装饰器中添加一些验证逻辑,可以确保函数或类的参数满足特定的要求,从而增加代码的健壮性。

    (5)性能优化:装饰器可以用于实现一些性能优化的技术,例如缓存结果、延迟计算等。这些装饰器可以在需要时提供更高效的计算或访问方式,从而提升程序的性能。

    (6)访问控制:装饰器可以用于实现访问控制的功能,例如限制某些函数或类的访问权限。通过在装饰器中添加一些权限验证逻辑,可以控制哪些用户或角色可以访问被修饰的函数或类。

    总的来说,装饰器提供了一种灵活而强大的方式,可以在不修改原始函数或类代码的情况下,为其添加额外的功能或行为。这使得代码更加模块化、可复用和可扩展,提高了代码的可读性和可维护性。因此,装饰器是 Python 编程中常用的技术之一。

    五、装饰器命名规范

    装饰器名字可以随便取吗?

    在编写装饰器时,理论上可以自由选择装饰器的名称。Python 中的装饰器本质上是一个函数或类,因此可以像命名其他函数或类一样自由选择名称。

    然而,良好的编程实践建议为装饰器选择有意义且具有描述性的名称,以便其他开发人员能够清楚地理解其作用和使用方式。使用清晰、具有描述性的名称可以提高代码的可读性,并使其他开发人员更容易理解和维护您的代码。

    此外,还应注意不要与 Python 内置函数、标准库或第三方库中已存在的名称冲突。这样可以避免潜在的命名冲突和混淆。

    总而言之,虽然在命名装饰器时有一定的自由度,但选择有意义和描述性的名称是一种良好的编程实践,可以使代码更易读、易于维护,并与其他代码保持一致。


    在python中常见的装饰器有**@property装饰器@abstractmethod 装饰器**,具体作用和使用方法可以参考我的另外两篇博文:
    @property 装饰器的作用和用法
    @abstractmethod 装饰器的作用和用法

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python装饰器介绍与使用指南

    发表回复