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

Python中的装饰器函数与其用法的讲解

发布时间:2023-06-21 17:42:13

Python中的装饰器函数是一种高级函数,可以用于在不修改原函数代码的情况下,对函数的行为进行扩展或改变。在Python中,装饰器函数常用在一些需要对函数进行预处理、后处理或调用跟踪的场景中。

一、装饰器函数的定义和用法

最基本的装饰器函数定义形式为:

def decorator_function(func):
    def wrapper(*args, **kwargs):
        # 在调用函数之前执行的操作
        result = func(*args, **kwargs)
        # 在调用函数之后执行的操作
        return result
    return wrapper

这个装饰器函数接受一个函数作为参数,并返回一个新的函数。在函数调用前后,装饰器函数可以执行我们需要的任何操作:例如检查参数、计时、日志记录等。下面简单介绍一下如何使用装饰器函数。

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before calling the function")
        result = func(*args, **kwargs)
        print("After calling the function")
        return result
    return wrapper

@my_decorator
def my_function():
    print("Hello from my_function!")

my_function()

这里通过在函数定义前加上@my_decorator的方式使用了装饰器函数。执行my_function()时,实际执行的是被my_decorator包装过的版本,因此我们在调用时会看到额外的打印信息:

Before calling the function
Hello from my_function!
After calling the function

二、在装饰器中传递参数

在装饰器中传递参数时,可以在外层定义一个函数,同时在其内部返回装饰器,内部装饰器接受函数作为参数并返回包装好的函数。这样可以达到消除闭包的效果,方便程序的维护和拓展。示例代码如下:

def repeat(num):
    def my_decorator(func):
        def wrapper(*args, **kwargs):
            for i in range(num):
                print("Before calling the function")
                result = func(*args, **kwargs)
                print("After calling the function")
            return result
        return wrapper
    return my_decorator

@repeat(num=3)
def my_function():
    print("Hello from my_function!")

my_function()

这里通过带参装饰器的形式,重复调用my_function()并记录结果:

Before calling the function
Hello from my_function!
After calling the function
Before calling the function
Hello from my_function!
After calling the function
Before calling the function
Hello from my_function!
After calling the function

三、使用functools.wrap()保持被装饰函数的元信息

当一个函数被装饰时,它的所有元信息(如函数名、文档字符串和参数列表等)将被覆盖,如果我们希望保留这些元信息,可以使用functools模块中的wrap函数来达到这个目的:

from functools import wrap

def my_decorator(func):
    @wrap(func)
    def wrapper(*args, **kwargs):
        print("Before calling the function")
        result = func(*args, **kwargs)
        print("After calling the function")
        return result
    return wrapper

@my_decorator
def my_function(a, b):
    """This function returns the sum of a and b"""
    return a + b

print(my_function(1, 2))
print(my_function.__name__)
print(my_function.__doc__)

打印结果如下:

Before calling the function
After calling the function
3
my_function
This function returns the sum of a and b

四、装饰器函数的应用

在Python中,装饰器函数通常被用于以下场景:

1. 身份验证

将一些需要登录权限的函数使用装饰器包装起来,这样就可以在每次调用这些函数时判断当前用户是否拥有相应权限。

2. 日志记录

将一些需要记录调用日志的函数使用装饰器包装起来,这样可以记录下每次调用的时间、输入输出参数等信息。

3. 性能测试

使用装饰器函数计算函数的运算时间、内存消耗量等性能指标。

五、自定义装饰器

自定义装饰器是Python中非常实用的技巧,它可以使我们在代码中将一些常用的操作提取出来,方便重复使用。这里我们介绍一个简单的示例,实现单文件内的函数调用顺序检查:

def callorder(prev):
    def wrapper(func):
        def checker(*args, **kwargs):
            if prev[0] != func.__name__:
                print("Wrong call order!")
            prev[0] = func.__name__
            return func(*args, **kwargs)
        return checker
    return wrapper

这个简单的装饰器函数接受一个参数prev,它的内部定义了一个闭包函数checker,当调用装饰器修饰的函数时,会检查前一个函数的名称是否与当前函数一致,如果匹配则执行函数,否则返回错误信息。

六、总结

Python中的装饰器函数是一种高级函数,可以轻松地在函数调用前后实现一些预处理、后处理或调用跟踪等操作,同时也可以很好地消除重复代码。通过合适地使用装饰器函数,我们可以更方便地构思程序的设计,并且使程序更加清晰简单。