详解Python 装饰器

Python装饰器(Decorator)可以在不更改原函数源代码的情况下,为函数添加一些额外的功能,是Python中非常重要的概念之一。本文将详细讲解Python装饰器的使用方法及实现过程。

1. 装饰器实现原理

在Python中,函数是一等公民,可以被当做变量、参数、返回值来使用。因此,Python装饰器就是利用函数作为对象,实现在不更改原有代码的情况下为函数添加额外功能的方法。

装饰器的基本语法如下:

@decorator_func
def func():
    pass

其中,decorator_func是一个接收函数作为参数的函数,它会在原函数func执行之前或之后执行一些自己的代码,从而实现对原函数的装饰。

2. 装饰器示例

2.1. 给函数添加计时器功能

给函数添加计时器功能,可以统计函数执行时间,示例代码如下:

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Time elapsed: {end_time - start_time:.2f} seconds")
        return result
    return wrapper

@timer
def my_func():
    time.sleep(2)
    print("Hello, world!")

my_func()

在上面的代码中,timer是一个装饰器函数,它接收一个函数func作为参数,返回一个新的函数wrapper,这个新函数会在原函数执行之前记录开始时间并在执行之后记录结束时间,并输出总共执行时间。

2.2. 给函数添加缓存功能

给函数添加缓存功能,可以避免反复计算相同的结果,提高函数执行效率,示例代码如下:

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

@memoize
def fibonacci(n):
    if n in (0, 1):
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(20))

在上面的代码中,memoize是一个装饰器函数,它接收一个函数func作为参数,返回一个新函数wrapper,这个新函数会在执行原函数时检查缓存中是否存在相同的参数,并返回缓存中的结果,如果没有则进行计算并把结果存入缓存中。在这个示例中,我们用memoize装饰了一个计算斐波那契数列的函数fibonacci,通过缓存已经计算过的数列来提高效率。

3. 装饰器的高级用法

3.1. 装饰器可以带参数

装饰器可以带参数,如下面的示例所示,我们可以给装饰器timer添加一个参数unit,用来指定时间单位:

def timer(unit="s"):
    def decorator(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()

            if unit == "s":
                elapsed_time = end_time - start_time
            elif unit == "ms":
                elapsed_time = (end_time - start_time) * 1000
            elif unit == "us":
                elapsed_time = (end_time - start_time) * 1000000
            else:
                raise Exception("Unsupported unit")

            print(f"Time elapsed: {elapsed_time:.2f} {unit}")
            return result
        return wrapper
    return decorator

@timer(unit="us")
def my_func():
    time.sleep(0.002)
    print("Hello, world!")

my_func()

在上面的例子中,我们定义了一个带参数的timer函数,它返回一个装饰器函数decorator,这个装饰器函数接收一个函数func作为参数,返回一个新函数wrapper。在wrapper函数中,根据传入的参数unit来决定输出时间的单位。

3.2. 装饰器可以被链式使用

装饰器可以被链式使用,如下面的示例所示,我们定义两个装饰器loggingauth_required,通过@logging@auth_required的组合来对一个函数进行装饰:

def logging(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__} with {args} {kwargs}")
        result = func(*args, **kwargs)
        print(f"Finished calling {func.__name__}")
        return result
    return wrapper

def auth_required(func):
    def wrapper(*args, **kwargs):
        if is_authenticated():
            return func(*args, **kwargs)
        else:
            raise Exception("Authentication failed")
    return wrapper

@logging
@auth_required
def my_func():
    print("Hello, world!")

my_func()

在上面的例子中,loggingauth_required都是装饰器函数,我们用@logging@auth_required的组合,先对函数进行身份验证(auth_required),成功后打印日志(logging)。

4.小结

本文介绍了Python装饰器的原理、基本语法和两个示例:给函数添加计时器功能和给函数添加缓存功能。此外,我们还介绍了装饰器的高级用法:装饰器可以带参数和被链式使用。

在实际开发中,装饰器是非常有用的工具,可以优雅地实现一些横切面的需求,比如日志记录、缓存、身份验证、权限控制等。希望本文对你理解Python装饰器有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Python 装饰器 - Python技术站

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

相关文章

  • Python中的函数参数类型检查

    Python中的函数参数类型检查是一个非常重要的功能,它可以在开发过程中避免参数类型错误的问题,从而提高代码的鲁棒性。在Python中,可以使用类型注解和第三方库等多种方式来实现参数类型检查。下面将详细介绍这些方式。 方式一:使用类型注解 在Python 3.x中,提供了一种类型注解的方式,可以在函数参数中添加标注,来指定参数的类型。在运行时,可以使用 __…

    python 2023年5月13日
    00
  • python钉钉机器人运维脚本监控实例

    下面是关于“Python钉钉机器人运维脚本监控实例”的完整攻略: 目录 介绍 使用步骤 配置机器人 运行脚本 示例说明 监控服务器CPU使用率 监控服务器磁盘空间 总结 介绍 钉钉机器人是钉钉提供的一种形式化的通信渠道,可以通过代码来调用钉钉机器人的API,实现以机器人的形式向钉钉群组发送消息。本篇攻略将介绍如何使用Python语言发送消息至钉钉机器人,以及…

    python 2023年5月23日
    00
  • Python selenium如何打包静态网页并下载

    使用Python及其库selenium可以方便地自动化执行web页面操作,并且可以将web页面中的数据和内容下载到本地进行处理。下面介绍如何使用Python和selenium将web页面静态化并下载。 1. 安装Python与selenium库 首先需要确保安装了Python及其库selenium。可以使用以下命令进行安装: pip install sele…

    python 2023年6月3日
    00
  • Python中使用haystack实现django全文检索搜索引擎功能

    让我们来详细讲解如何使用Haystack实现Django全文检索搜索引擎功能。 简介 Haystack是一个免费的开源搜索引擎框架,它可以轻松地在Django中实现全文检索搜索引擎功能。Haystack支持多个搜索后端,包括Solr、Elasticsearch和Whoosh等。 安装Haystack 在Django项目中使用Haystack需要先安装它。可以…

    python 2023年6月6日
    00
  • 使用 Pushes Create Api with Python 将文件上传/推送到 Azure Devops Repo 时出现无效的 Json 错误

    【问题标题】:Invalid Json error when Uploading/pushing a file to Azure Devops Repo using Pushes Create Api with Python使用 Pushes Create Api with Python 将文件上传/推送到 Azure Devops Repo 时出现无效的 …

    Python开发 2023年4月6日
    00
  • python调用c++传递数组的实例

    对于这个问题,我可以提供以下完整的攻略来解决它。 Python调用C++传递数组的实例 在Python中调用C++代码时,我们可能会需要传递数组类型的参数。对于这种情况,我们可以使用ctypes库来帮助我们完成C++和Python之间的数据交换。下面我将演示如何使用ctypes来实现Python调用C++传递数组的实例。 示例1:Python传递列表,C++…

    python 2023年6月5日
    00
  • 浅谈python多线程和队列管理shell程序

    这里是关于“浅谈python多线程和队列管理shell程序”的完整攻略。 1. 什么是Python多线程和队列管理 Python是一种高级编程语言,具有易学易用、灵活性高等特点。多线程和队列管理则是Python中的两个非常重要的概念。 1.1 多线程 多线程指的是在一个程序中同时运行多个线程,实现多个任务同时进行,提高程序的运行效率。Python提供了thr…

    python 2023年5月18日
    00
  • Python sklearn KFold 生成交叉验证数据集的方法

    Python中的机器学习库scikit-learn(sklearn)提供了KFold方法来生成交叉验证数据集,通过交叉验证评估模型预测性能。KFold方法将数据集划分为K个互斥子集,每次取其中一个子集作为验证集,其余K-1个子集作为训练集,循环K次验证模型。 下面是使用Python中的sklearn库进行KFold交叉验证数据集生成的步骤及示例说明: 步骤1…

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