你好,我是你们的老朋友,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多年的老司机,应该会比较偏爱装饰器,所以刚入门的朋友,大家慢慢来。
一起加油!
继续阅读
阅读原文