Python装饰器实现方法及应用场景详解

yizhihongxing

Python装饰器实现方法及应用场景详解

1. 概述

装饰器是 Python 中非常重要的概念,几乎所有 Python 框架都大量使用到了装饰器。它可以用于功能增强、日志处理、输入验证和安全控制等场景。

装饰器本质上是一个 Python 函数或类,并在不改变原函数/方法定义的基础上对其进行增强。Python 中借助函数式编程的特点,可以很方便地实现装饰器。

2. Python装饰器实现方法

装饰器可以使用函数或类实现,下面分别介绍。

2.1 函数实现装饰器

函数装饰器包装器的通用格式如下所示:

def decorator(func):
    def wrapper(*args, **kwargs):
        # 在调用原函数前进行增强操作
        res = func(*args, **kwargs)
        # 在调用原函数后进行增强操作
        return res
    return wrapper

将被装饰的函数作为参数传给装饰器函数,返回一个新的经过增强的函数并替换掉原函数。

wrapper 函数中,可以在调用原函数前后进行额外的逻辑处理。

例如,下面的代码实现了一个简单的计算程序,加入了装饰器对输入的检查功能,如果输入值为负数则自动转换成正数:

def check_input(func):
    def wrapper(*args, **kwargs):
        for arg in args:
            if arg < 0:
                print(f"Warning: Invalid input value ({arg}), automatically converts it to positive value.")
                arg = -arg
        return func(*args, **kwargs)
    return wrapper

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

print(add(1, -2)) # 输出:Warning: Invalid input value (-2), automatically converts it to positive value.
                  #      -1

在上面的代码中,add 函数被 check_input 装饰器装饰,该装饰器会检查传入参数的值是否为负数,若是则转化为相应正数,然后才调用 add 函数,返回结果。

2.2 类实现装饰器

类装饰器的实现方式类似于函数装饰器。一个类装饰器通常具有 __call__ 方法,且能够接受被装饰的方法或函数作为参数,并在其上执行增强操作。

class Decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        # 在调用原函数前进行增强操作
        res = self.func(*args, **kwargs)
        # 在调用原函数后进行增强操作
        return res

实现后,我们可以使用装饰器类对函数进行装饰。

例如,下面的代码实现了一个简单的装饰器类,该装饰器类在调用被装饰的函数前后打印一行信息:

class Logger:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f"Call {self.func.__name__} function...")
        res = self.func(*args, **kwargs)
        print(f"{self.func.__name__} function finished.")
        return res

@Logger
def foo(x, y):
    return x + y

print(foo(1, 2)) # 输出:Call foo function...
                 #      foo function finished.
                 #      3

在上面的代码中,foo 函数被 Logger 装饰器装饰,该装饰器会在调用 foo 函数前后打印一行信息,然后才调用 foo 函数,返回结果。

3. 装饰器应用场景

3.1 功能增强

装饰器可以对函数进行增强。例如,在框架中处理请求/响应对象时,可以使用装饰器简化代码复杂度。

例如,下面的代码实现了一个装饰器类,对 Flask 框架中的请求进行记录:

def record_request(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(f"Request URL: {request.url}")
        print(f"Request IP Address: {request.remote_addr}")
        print(f"Request Method: {request.method}")
        print(f"Request Time: {end - start:.3f}s")
        return res
    return wrapper

@app.route("/")
@record_request
def hello():
    return "Hello World!"

在上面的代码中,record_request 装饰器类会在调用 hello 函数前后记录请求 URL、IP地址、请求方法和请求时间。

Flask 能够接收来自浏览器或其他客户端的HTTP请求,它内置了多个数据结构来处理请求,其中重要的一点就是当前请求的信息都在一个名为request的全局变量里,可以通过 Flask 的request模块来使用。

3.2 输入验证

装饰器可以对函数的输入参数类型进行检查。例如,在 Web 开发中需要对输入内容进行验证,以保证数据的有效性和安全性。

例如,下面的代码实现了一个装饰器函数,对输入的数值范围进行检查。

def check_range(min_val, max_val):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for arg in args:
                if arg < min_val or arg > max_val:
                    raise ValueError(f"Invalid value for parameter ({arg}), should between ({min_val}, {max_val}).")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@check_range(min_val=0, max_val=100)
def square(x):
    return x * x

print(square(3))
print(square(-1)) # 抛出异常:ValueError: Invalid value for parameter (-1), should between (0, 100).

在上面的代码中,check_range 装饰器函数会检查函数输入的参数值是否在指定的范围内,如果不在所指定的范围内,则抛出异常(ValueError),提示用户输入有误。

3.3 输出记录

装饰器可以对函数的输出结果进行记录。例如,记录函数的返回结果,方便后续分析和调试。

下面是一个简单示例程序,演示对函数输出记录的实现:

def log_result(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        print(f"Function {func.__name__} returned: {res}")
        return res
    return wrapper

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

add(1, 2) # 输出:Function add returned: 3

在上面的程序中, add 函数被 log_result 装饰器装饰,该装饰器会在调用完 add 函数后,记录函数的返回结果。

4. 总结

装饰器是 Python 中应用广泛的编程语法,在函数功能扩展、输入输出检查、日志记录等场景中都有广泛应用。只要掌握装饰器的实现方式和应用场景,就能有效提升 Python 中程序开发的效率和质量。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python装饰器实现方法及应用场景详解 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • Python – 如何使用 PySAL 计算交互式空间自相关 (Moran I)?

    【问题标题】:Python – How do I compute interactive spatial autocorrelation (Moran I) using PySAL?Python – 如何使用 PySAL 计算交互式空间自相关 (Moran I)? 【发布时间】:2023-04-04 11:05:01 【问题描述】: 我在 PostgreSQ…

    Python开发 2023年4月6日
    00
  • 编译器与解释器原理

    上一章我们已经了解到,编程语言其实就是一种我们人类易于理解的程序语言。我们用这种编程语言编写的程序就称为源代码。这些源代码是通过翻译器这么个东西,被翻译成二进制指令,从而让计算机能够执行我们的指令。 那么,这其中发挥很大作用的翻译器又是怎么回事? 编译型语言与解释型语言 其实,翻译器不止一种。我们根据翻译器翻译的时机,将它分为了编译器和解释器。 相应的,编程…

    2022年10月25日
    00
  • Python机器学习实战之k-近邻算法的实现

    以下是关于“Python机器学习实战之k-近邻算法的实现”的完整攻略: 简介 k-近邻算法是一种常见的机器学习算法,可以用于分类和回归问题。本教程将介绍如何使用Python实现k-近邻算法,并讨论如何使用该算法进行分类。 步骤 1.导入库和数据 首先,我们需要导入必要的库,包括numpy和matplotlib。在Python中,可以使用以下代码导入这些库: …

    python 2023年5月14日
    00
  • 利用Python实现批量下载上市公司财务报表

    利用Python实现批量下载上市公司财务报表 简介 本文将介绍如何利用Python和第三方库实现批量下载上市公司财务报表。我们将以下载深交所上市公司2019年半年度报告为例。 步骤 步骤一:确定下载链接 首先我们需要确定要下载哪些报表,以及它们的下载链接。深交所上市公司2019年半年度报告的下载链接为: http://www.szse.cn/disclosu…

    python 2023年6月3日
    00
  • python实现对doc,txt,xls文档的读写操作

    当然,我很乐意为您提供“Python实现对doc,txt,xls文档的读写操作”的完整攻略。以下是详细步骤和示例。 Python实现对doc,txt,xls文档读写操作 在Python中,我们使用不同的库来实现对doc,txt,xls文档的读写操作。具体步骤如下: 1. 使用Python内置的open函数读写txt文档 对于txt文档,我们可以使用Pytho…

    python 2023年5月13日
    00
  • 解决vscode python print 输出窗口中文乱码的问题

    当你在VSCode 中使用 Python 编写代码时,如果输出的内容包含中文,有可能会出现乱码的情况。这是因为 VSCode 的输出窗口默认使用 utf-8 编码,而 Windows 的终端默认使用 gbk 编码。下面给出两种解决方法: 方法一:设置 VSCode 输出窗口编码 在 VSCode 的配置文件中设置输出窗口的编码为 utf-8 即可解决乱码的问…

    python 2023年5月20日
    00
  • python pandas处理excel表格数据的常用方法总结

    我将为你详细介绍“python pandas处理excel表格数据的常用方法总结”的完整实例教程。 标题一:pandas读取excel表格数据 pandas提供的read_excel()函数可以方便地读取excel表格数据。以下是一个读取excel数据的示例: import pandas as pd # 读取excel数据 excel_data = pd.r…

    python 2023年5月13日
    00
  • 利用Python读取文件的四种不同方法比对

    我来为你详细讲解利用Python读取文件的四种不同方法比对的完整攻略。 一、读取文件的四种不同方法 读取文件是在实际编程中会经常用到的操作之一。Python中常用的文件读取方法有四种,分别是: 使用open函数读取文件 使用with语句读取文件 使用标准库中的fileinput模块读取文件 使用pandas库读取文件 接下来我们一一详细介绍这四种方法,并对它…

    python 2023年6月5日
    00
合作推广
合作推广
分享本页
返回顶部