zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Q527:理解Python装饰器的3个案例

Python案例 理解 装饰
2023-06-13 09:16:30 时间

你好,我是你们的老朋友,zhenguo!

这篇文章来自同学的提问,问题就是如何系统理解Python装饰器,我在此总结如下。

1 装饰器就是函数

Python 中的装饰器是一种高阶函数,可以在不修改函数的情况下将新的功能添加到函数中。

装饰器使用 @ 语法糖,并且可以用来装饰函数、类和方法。

在本质上,装饰器是一个函数,它必须是接受一个函数作为参数,并返回一个函数。

返回的函数包含了原来函数的功能,并额外添加了新的功能。

2 装饰器案例一:实现翻倍

例如,假设你有一个函数 add,它接受两个参数并返回它们的和:

def add(x, y):
    return x + y

你可以使用装饰器来创建一个新的函数 add_twice,它将原来的加法函数包装在自己的功能中。

def add_twice(func):
    def wrapper(x, y):
        return func(x, y) + func(x, y)
    return wrapper

# 使用 @ 语法糖装饰函数
@add_twice
def add(x, y):
    return x + y

print(add(1, 2))  # 输出: 6

上面的代码使用了装饰器语法,这样你就可以在不修改 add 函数的情况下添加新的功能了。

当你调用 add(1, 2) 时,实际上是调用了 add_twice 函数返回的新函数,这个新函数会调用原来的 add 函数两次,并将结果相加。

3 装饰器案例二:实现结果缓存

装饰器的一个常见用途是用来缓存函数结果。

例如,假设你有一个函数 expensive_func,它需要花费大量时间计算结果,你希望能够缓存这个函数的结果,避免重复计算。你可以使用装饰器来实现这个功能:

def cache(func):
    # 创建一个缓存字典
    cache = {}

    # 创建包装器函数
    def wrapper(*args):
        # 如果缓存字典中有对应的值,则直接返回
        if args in cache:
            return cache[args]
        # 否则调用原函数并将结果缓存起来
        result = func(*args)
        cache[args] = result
        return result

    return wrapper

# 使用 @ 语法糖装饰函数
@cache
def expensive_func(x, y):
    # 这里是计算代码...
    pass

print(expensive_func(1, 2))  # 计算并缓存结果
print(expensive_func(1, 2))  # 直接使用缓存的结果
print(expensive_func(3, 4))  # 计算并缓存新的结果

4 装饰器案例三:接受参数的装饰器

装饰器还可以接受参数。要实现这个功能,你需要创建一个函数,这个函数接受参数并返回装饰器函数。

例如,假设你想创建一个装饰器,它可以在函数调用之前和之后打印消息:

def log(prefix):
    def log_decorator(func):
        def wrapper(*args, **kwargs):
            print(prefix, "before calling", func.__name__)
            result = func(*args, **kwargs)
            print(prefix, "after calling", func.__name__)
            return result
        return wrapper
    return log_decorator

# 使用 @ 语法糖装饰函数,并提供参数
@log("DEBUG")
def add(x, y):
    return x + y

print(add(1, 2))

上面的代码会输出:

DEBUG before calling add
DEBUG after calling add

注意,log 函数返回了另一个函数 log_decorator,而 log_decorator 函数又返回了另一个函数 wrapper。这个过程称为装饰器嵌套。

装饰器是 Python 中的一个强大特性,它可以让你在不修改函数代码的情况下为函数添加额外的功能。若你是使用Python多年的老司机,应该会比较偏爱装饰器,所以刚入门的朋友,大家慢慢来。

一起加油!