Python 装饰器:让你的代码更优雅

172 阅读4分钟

什么是装饰器?

装饰器是一个函数,它接收另一个函数作为参数,并返回一个新的函数。简单来说,装饰器可以“包裹”一个函数,在函数执行之前或之后添加额外的功能。这样做的好处是,你可以通过装饰器增强函数的功能,而无需改变原函数的代码。

为什么要使用装饰器

  • 代码复用:  将通用的功能(如日志记录、性能分析)封装成装饰器,可以在多个函数中复用,避免重复代码。
  • 代码简洁:  避免在每个函数中都编写相同的额外逻辑,使代码更加清晰易读。
  • 可扩展性:  方便地添加或删除功能,而无需修改原函数代码。

装饰器的基本语法

装饰器通常通过@符号来使用,这个符号被称为装饰器语法糖。它实际上是函数调用的一种简化写法。

def decorator(func):
    def wrapper(*args, **kwargs):
        print("执行装饰器前的操作")
        result = func(*args, **kwargs)
        print("执行装饰器后的操作")
        return result

    return wrapper


@decorator
def say_hello(name):
    print(f"Hello, {name}!")


say_hello("Alice")

输出结果:

执行装饰器前的操作
Hello, Alice!
执行装饰器后的操作

在这个例子中,say_hello 函数被 decorator 装饰器包装。每次调用 say_hello() 时,都会先执行装饰器中的操作,再执行 say_hello() 的原始功能。

装饰器的工作原理

  1. decorator 函数接收 say_hello 函数作为参数。
  2. decorator 函数返回一个新的函数 wrapper,它在执行时先做一些额外的操作,然后再调用原始的 say_hello 函数。
  3. 使用 @decorator 语法实际上是将 say_hello = decorator(say_hello)

多个装饰器的应用

Python支持多个装饰器应用在一个函数上。多个装饰器执行顺序分为函数执行之前是从上到下的执行,函数执行之后按照从下往上的执行顺序。

def decorator1(func):
    def wrapper():
        print("Decorator 1: Before function")
        func()
        print("Decorator 1: After function")
    return wrapper

def decorator2(func):
    def wrapper():
        print("Decorator 2: Before function")
        func()
        print("Decorator 2: After function")
    return wrapper

@decorator1
@decorator2
def say_hello():
    print("Hello, World!")

say_hello()

输出结果:

Decorator 1: Before function
Decorator 2: Before function
Hello, World!
Decorator 2: After function
Decorator 1: After function

装饰器的高级应用

1. 带参数的装饰器

使用装饰器工厂实现

有时你可能需要为装饰器传递参数。这就涉及到装饰器的“嵌套”写法。下面是一个带参数的装饰器的例子:

def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def say_hello():
    print("Hello, World!")

say_hello()

输出结果:

Hello, World!
Hello, World!
Hello, World!

在这个例子中,repeat 是一个带参数的装饰器,它会重复执行被装饰的函数指定的次数。

2. 装饰器与返回值

默认情况下,装饰器会返回原函数的执行结果。但你也可以根据需求修改返回值。例如,下面的装饰器会在函数执行后返回一个固定的值:

def return_42(func):
    def wrapper(*args, **kwargs):
        result =func(*args, **kwargs)  # 执行原函数
        return 42  # 返回固定的值

    return wrapper


@return_42
def add(a, b):
    return a + b


result = add(1, 2)
print(result)

输出结果:

42

3. 类装饰器

装饰器不仅仅可以用于函数,它还可以应用于类。类装饰器的原理和函数装饰器类似,不同的是,它接收的参数是类本身,而不是函数。

def add_method(cls):
    def new_method(self):
        print("This is a new method!")
    cls.new_method = new_method
    return cls

@add_method
class MyClass:
    def __init__(self, name):
        self.name = name

obj = MyClass("Alice")

obj.new_method() # type: ignore

输出结果:

This is a new method!

在这个例子中,我们通过装饰器 add_methodMyClass 类动态地添加了一个新的方法 new_method

总结

装饰器是Python中一种非常灵活且强大的工具。它能够帮助我们在不修改原始代码的情况下,扩展函数或方法的功能。理解和掌握装饰器的使用,将使你在Python编程中更加高效和优雅。