欢迎访问宙启技术站
智能推送

Python中的Decorator函数

发布时间:2023-06-23 15:46:14

Python中的装饰器(Decorator)是一种特殊的函数,可以修改其他函数的行为。它可以在不修改原函数代码的情况下,添加额外的功能,例如:记录日记、计时、身份验证、缓存等等。

一、装饰器的基本用法

使用 python 装饰器,就可以把对函数的修饰看作是一个函数,那么它实际上是一个接受函数返回一个函数的高阶函数。常见的装饰器有很多种,比较常见的如下。

1. 函数装饰器

示例如下:

def func_decorator(func):
    def wrapper(*args, **kwargs):
        # Do something before the function is called
        print("do something before the function is called")
        # Call the function
        result = func(*args, **kwargs)
        # Do something after the function is called
        print("do something after the function is called")
        return result

    return wrapper

@func_decorator
def my_function(x, y):
    return x + y

my_result = my_function(2, 3)
print(my_result)   # output: 5

解释:

该示例中,我们定义了一个装饰器函数 func_decorator,接受一个函数作为输入,并返回一个新的函数。新的函数 wrapper 在原函数 my_function 调用时会被执行,因为我们在 my_function 上添加了 @func_decorator 装饰器。这就相当于把 my_function 函数传递给了 func_decorator,因此 wrapper 函数所执行的内容就会在 my_function 中执行。

在该示例的 wrapper 函数中,我们首先添加了 “do something before the function is called” 的语句,然后调用了原本的函数,并把结果保存到变量 result 中。最后输出了一个带有 “do something after the function is called” 字符串的语句,并返回了计算的结果。

2. 类装饰器

类装饰器采用相同的逻辑,只是翻译成了类方法。

示例如下:

class ClassDecorator(object):
    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        print("do something before the function is called")
        result = self.f(*args, **kwargs)
        print("do something after the function is called")
        return result

@ClassDecorator
def my_function(x, y):
    return x + y

my_result = my_function(2, 3)
print(my_result)   # output: 5

解释:

该示例中,我们定义了一个类 ClassDecorator,它接受一个函数作为输入,并存储在 __init__ 函数中。在调用过程中,我们在 __call__ 方法中添加了所需的代码,并调用保存的函数。

然后,我们在 my_function 函数上添加了 @ClassDecorator 装饰器,这会把我们的 my_function 函数传递给 ClassDecorator 类的实例化对象。此时 my_function 会被替换为一个调用 ClassDecorator 实例的 __call__ 方法的新对象。因此,新对象在执行 my_function 时,会在执行前后执行我们自定义的方法。

II. 装饰器的应用

装饰器的应用有很多,其中最常见的应用是在函数上添加日志记载、计时、数据验证、缓存等功能。下面介绍一些常见的装饰器。

1. 计时器装饰器

计时器装饰器可以用于评估函数的性能。例如,我们可以用这个装饰器计算某个函数的执行时间。

示例如下:

import time

def timer(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        result = func(*args, **kwargs)
        t2 = time.time()
        print(f'{func.__name__} took {t2-t1} seconds to execute')
        return result
    return wrapper

@timer
def my_function(x, y):
    time.sleep(2)
    return x + y

result = my_function(2, 3)

解释:

在这个例子中, timer 装饰器接受一个函数作为输入,并定义一个名为 wrapper 的内部函数。 wrapper 函数首先记录了起始时间,执行函数,然后记录结束时间。输出结果表明,该函数的执行时间大约为2秒。

2. 日志记录装饰器

日志记录装饰器可以用于在函数执行期间记录日志。这在调试代码或记录函数执行的详细信息时非常有用。

示例如下:

import logging

logging.basicConfig(level=logging.INFO)

def logger(func):
    def wrapper(*args, **kwargs):
        logging.info(f'[INFO] Function "{func.__name__}" was called with args: {args}, {kwargs}')
        result = func(*args, **kwargs)
        logging.info(f'[INFO] Result: {result}')
        return result

    return wrapper

@logger
def my_function(x, y):
    return x + y

my_function(2, 3)

解释:

在这个例子中, logger 装饰器定义了一个内部函数 wrapper,用于实现日志记录功能。在执行函数时,我们可以使用 logging 模块记录执行信息。

在这个示例中, logger 装饰器添加了函数被调用信息和函数执行结果的日志记录。运行该程序会输出以下结果:

INFO:root:[INFO] Function "my_function" was called with args: (2, 3), {}
INFO:root:[INFO] Result: 5

3. 缓存装饰器

缓存装饰器可以用于存储函数的计算结果,并在下次调用时使用已存储的结果,以提高代码效率。

示例如下:

def memoize(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            return cache[args]
        else:
            result = func(*args)
            cache[args] = result
            return result
    return wrapper

@memoize
def fibonacci(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))

解释:

在这个示例中,我们定义了一个 memoize 装饰器。 wrapper 函数首先检查缓存中是否有输入参数的结果。如果结果已经缓存,则返回缓存的结果,否则计算结果并将它添加到缓存中。

fibonacci 函数使用 memoize 装饰器,这意味着在调用 fibonacci 函数时,会先检查缓存中是否有结果。

4. 身份验证装饰器

身份验证装饰器可以用于验证用户的身份,通常被用于一些敏感操作,例如:删除、修改、新增等操作。

示例如下:

def authenticated(func):
    def wrapper(*args, **kwargs):
        if is_authenticated_user():
            result = func(*args, **kwargs)
            return result
        else:
            return 'You must be authenticated to access this function!'
    return wrapper

@authenticated
def my_function():
    return 'This function requires authentication'

print(my_function())

解释:

在这个示例中,我们定义了一个 authenticated 装饰器。 wrapper 函数首先检查用户是否验证并通过身份验证后,才调用原始函数。

my_function 函数使用 authenticated 装饰器,这意味着在调用 my_function 函数时,会先检查用户是否验证通过。

总结:

Python中的Decorator函数适用于在不修改原函数代码的情况下为函数添加额