Python全景系列之装饰器使用的全面讲解

 更新时间:2023年05月31日 14:22:25   作者:techlead_krischang  
装饰器在Python中扮演了重要的角色,文将深入探讨装饰器的所有相关主题,包括装饰器的基础知识、实现与使用、工作原理等,需要的可以参考一下

Python 装饰器深入探讨

在 Python 中,装饰器提供了一种简洁的方式,用来修改或增强函数和类的行为。装饰器在语法上表现为一个前置于函数或类定义之前的特殊标记:

@simple_decorator
def hello_world():
    print("Hello, world!")

在这个例子中,simple_decorator 是一个装饰器,它作用于下方的 hello_world 函数。装饰器在概念上就像一个包装器,它可以在被装饰的函数执行前后插入任意的代码,进而改变被装饰函数的行为。

参数化装饰器

我们还可以进一步将装饰器参数化,这让装饰器的行为更具灵活性。比如,我们可以定义一个装饰器,让它在函数执行前后打印自定义的消息:

def message_decorator(before_message, after_message):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(before_message)
            result = func(*args, **kwargs)
            print(after_message)
            return result
        return wrapper
    return decorator

@message_decorator("Start", "End")
def hello_world():
    print("Hello, world!")

在这个例子中,message_decorator 是一个参数化装饰器,它接受两个参数,分别代表函数执行前后要打印的消息。

理解装饰器的工作原理

在 Python 中,函数是第一类对象。这意味着函数和其他对象一样,可以作为变量进行赋值,可以作为参数传给其他函数,可以作为其他函数的返回值,甚至可以在一个函数里面定义另一个函数。这个特性是实现装饰器的基础。

def decorator(func):
    def wrapper():
        print('Before function execution')
        func()
        print('After function execution')
    return wrapper

def hello_world():
    print('Hello, world!')

decorated_hello = decorator(hello_world)
decorated_hello()

在这个例子中,decorator 函数接收一个函数 hello_world 作为参数,并返回了一个新的函数 wrapped_func。这个新函数在 hello_world 函数执行前后分别打印一条消息。我们可以看到,装饰器实际上是一个返回函数的函数。

函数签名保持

默认情况下,装饰器会“掩盖”掉原函数的名字和文档字符串。这是因为在装饰器内部,我们返回了一个全新的函数。我们可以使用 functools.wraps 来解决这个问题:

import functools
def decorator(func):
    @functools.wraps(func)
    def wrapper():
        print('Before function execution')
        func()
        print('After function execution')
    return wrapper
@decorator
def hello_world():
    "Prints 'Hello, world!'"
    print('Hello, world!')
print(hello_world.__name__)
print(hello_world.__doc__)

这样,使用装饰器后的函数名和文档字符串能够保持不变。

Python 装饰器的应用实例

装饰器在实际的 Python 编程中有许多应用场景,比如日志记录、性能测试、事务处理、缓存、权限校验等。

一个常见的应用就是使用装饰器进行日志记录:

import logging

def log_decorator(func):
    logging.basicConfig(level=logging.INFO)
    
    def wrapper(*args, **kwargs):
        logging.info(f'Running "{func.__name__}" with arguments {args} and kwargs {kwargs}')
        result = func(*args, **kwargs)
        logging.info(f'Finished "{func.__name__}" with result {result}')
        return result
    
    return wrapper

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

这个装饰器记录了函数的名称,函数调用的参数,以及函数返回的结果。

装饰器链

Python 允许我们将多个装饰器应用到一个函数上,形成一个装饰器链。例如,我们可以同时应用日志装饰器和性能测试装饰器:

import time
import logging
from functools import wraps

def log_decorator(func):
    logging.basicConfig(level=logging.INFO)
    
    @wraps(func)
    def wrapper(*args, **kwargs):
        logging.info(f'Running "{func.__name__}" with arguments {args} and kwargs {kwargs}')
        result = func(*args, **kwargs)
        logging.info(f'Finished "{func.__name__}" with result {result}')
        return result

    return wrapper

def timer_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f'Function "{func.__name__}" took {end_time - start_time} seconds to run.')
        return result

    return wrapper

@log_decorator
@timer_decorator
def add(x, y):
    time.sleep(2)
    return x + y

在这个例子中,@log_decorator 和 @timer_decorator 两个装饰器被同时应用到 add 函数上,它们分别负责记录日志和测量函数运行时间。

One More Thing: 自动注册装饰器

一个有趣的装饰器应用是自动注册。这个装饰器会在装饰函数时自动将函数添加到一个列表或字典中,这样我们就可以在程序的其他地方访问到这个列表或字典,知道有哪些函数被装饰过。

# 装饰器将函数注册到一个列表中
def register_decorator(func_list):
    def decorator(func):
        func_list.append(func)
        return func
    return decorator

# 自动注册函数
registered_functions = []
@register_decorator(registered_functions)
def foo():
    pass

@register_decorator(registered_functions)
def bar():
    pass

print(registered_functions)  # 输出: [<function foo at 0x10d38d160>, <function bar at 0x10d38d1f0>]

这个装饰器可以用于自动注册路由、插件系统、命令行参数处理等场景,能够大大提高代码的灵活性和可扩展性。

总结

Python 装饰器是一种强大的工具,它可以让我们更有效地管理和组织代码。希望通过这篇文章,你能够更深入地理解装饰器的工作原理和用法,从而在你的项目中更好地使用装饰器。

到此这篇关于Python全景系列之装饰器使用的全面讲解的文章就介绍到这了,更多相关Python装饰器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python如何提取chm数据

    Python如何提取chm数据

    这篇文章主要介绍了Python如何提取chm数据,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • 简单了解python关键字global nonlocal区别

    简单了解python关键字global nonlocal区别

    这篇文章主要介绍了简单了解python关键字global nonlocal区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Python中的Decimal使用及说明

    Python中的Decimal使用及说明

    这篇文章主要介绍了Python中的Decimal使用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • python中多个装饰器的执行顺序详解

    python中多个装饰器的执行顺序详解

    装饰器是程序开发中经常会用到的一个功能,也是python语言开发的基础知识。这篇文章主要介绍了python中多个装饰器的执行顺序详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • python绘制条形图方法代码详解

    python绘制条形图方法代码详解

    这篇文章主要介绍了python绘制条形图方法代码详解,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • Django使用mysqlclient服务连接并写入数据库的操作过程

    Django使用mysqlclient服务连接并写入数据库的操作过程

    这篇文章主要介绍了Django使用mysqlclient服务连接并写入数据库,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • Python3.6日志Logging模块简单用法示例

    Python3.6日志Logging模块简单用法示例

    这篇文章主要介绍了Python3.6日志Logging模块简单用法,结合实例形式分析了Python3.6环境下日志Logging模块设置格式、文件流输出相关操作技巧,需要的朋友可以参考下
    2018-06-06
  • python网络爬虫精解之Beautiful Soup的使用说明

    python网络爬虫精解之Beautiful Soup的使用说明

    简单来说,Beautiful Soup 是 python 的一个库,最主要的功能是从网页抓取数据,Beautiful Soup 提供一些简单的、python 式的函数用来处理导航、搜索、修改分析树等功能,需要的朋友可以参考下
    2021-09-09
  • 利用Python的pandas数据处理包将宽表变成窄表

    利用Python的pandas数据处理包将宽表变成窄表

    这篇文章主要介绍了利用Python的pandas数据处理包将宽表变成窄表,文章通过围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • Python 比较两个 CSV 文件的三种方法并打印出差异

    Python 比较两个 CSV 文件的三种方法并打印出差异

    这篇文章主要介绍了Python 比较两个 CSV 文件并打印出差异,本文将讨论比较两个 CSV 文件的各种方法,我们将包括执行此操作的最“Pythonic”方式和可帮助简化此任务的外部 Python 模块,需要的朋友可以参考下
    2023-06-06

最新评论