详解Python 装饰器

  • Post category:Python

Python 装饰器是 Python 编程语言中一种非常常用的技术,可以在不改变原函数代码的情况下,通过对函数进行装饰,改变函数的行为,使其具有额外的功能。在本文中,我们将介绍 Python 装饰器的使用方法,包括装饰器的基本概念、应用场景以及两个具体的例子说明。

装饰器的基本概念

定义

简单来说,Python 装饰器就是在既有函数定义的基础上,动态地增加功能的功能函数,可以理解为一个包装器,它最典型的应用场景是给一个函数或者方法增加新的功能或者行为,比如权限验证、日志记录或者性能测试等等。

原理

装饰器本质上就是一个Python函数,它可以接受一个函数对象作为参数,同时返回一个新的函数对象。这个新的函数对象通常会在原有函数对象的基础上加上一些新的功能。

语法

Python 装饰器的语法格式比较简单,我们可以在一个函数定义前面使用 @ 标志,来装饰这个函数,比如下面这个例子:

@decorator
def func():
    pass

这里的 decorator 就是一个装饰器的函数对象,它可以是任意的 Python 函数。

Python 装饰器的应用场景

Python 装饰器最常见的应用场景包括:

  • 计时器:记录某个函数运行的时间;
  • 日志记录:记录某个函数的执行日志;
  • 权限验证:验证某个用户是否有操作权限;
  • 缓存:缓存某个函数的执行结果,提升程序性能。

使用装饰器的具体例子

装饰器实现计时器

下面是一个具体的装饰器例子,用来记录函数运行的时间:

import time

def time_it(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print("函数 %s 执行时间: %f 秒" % (func.__name__, end - start))
        return result
    return wrapper

上面这个装饰器定义了一个名叫 time_it 的函数,我们可以将它应用到任意一个函数中,并在函数执行结束后打印出函数的执行时间。现在我们来看一个使用装饰器的具体例子:


@time_it
def fibonacci(n):
    if n < 2:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

我们用 @time_it 装饰器来修饰了 fibonacci 函数,现在我们再次调用这个函数:

>>> fibonacci(30)
函数 fibonacci 执行时间: 0.545168 秒
832040

这个装饰器成功记录了 fibonacci 函数的执行时间。

装饰器实现缓存

下面是一个装饰器例子,用来实现一个简单的缓存:

def cache(func):
    cached_result = {}

    def wrapper(n):
        if n in cached_result:
            return cached_result[n]
        else:
            result = func(n)
            cached_result[n] = result
            return result

    return wrapper

这个装饰器定义了一个名叫 cache 的函数,我们可以将它应用到任意一个函数中,并在函数执行结束后将结果缓存起来。现在我们来看一个使用装饰器的具体例子:

@cache
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

我们用 @cache 装饰器来修饰了 factorial 函数,现在我们再次调用这个函数:

>>> factorial(10)
3628800
>>> factorial(5)
120

factorial 函数的前两次调用都会被缓存下来,以后的调用会直接从缓存中获取结果,不需要再次执行计算。

总结

Python 装饰器是 Python 编程语言中非常常用的技术,它可以在不改变原函数代码的情况下,通过对函数进行装饰,改变函数的行为。在本文中,我们介绍了 Python 装饰器的基本概念、应用场景以及两个具体的例子说明,希望这篇文章能够帮助你更好地掌握 Python 装饰器的使用方法。