Python 函数装饰器--最全面的详细的装饰器文章
发布日期:2021-05-20 05:59:04 浏览次数:22 分类:精选文章

本文共 3489 字,大约阅读时间需要 11 分钟。

Python 装饰器入门指南

装饰器是 Python 中一个强大的工具,能够帮助开发者在不修改现有函数代码的情况下,增添新的功能。这种功能让你的代码更加简洁、可维护且更符合 Python 的范式。以下将引导你逐步理解装饰器的概念、用法以及实际应用场景。

一、装饰器的基础概念

装饰器(Decorator)是一种函数,用于修改或扩展另一个函数的行为。在 Python 中,装饰器可以是普通函数或者类,能够通过嵌套或参数传递来实现对目标函数的装饰。

装饰器的基本结构:

def a_new_decorator(func):
def wrapped(*args, **kwargs):
# 在函数执行前后做一些额外的事情
return func(*args, **kwargs)
return wrapped

当使用装饰器时,函数被装饰后返回的一般函数对象,就像 wrapped 中定义的函数。wrapped 可以执行额外的操作,然后调用原始函数 func

二、使用装饰器的步骤

  • 定义装饰器:

    首先,定义一个装饰器函数,该函数接收目标函数作为参数。

  • 装饰目标函数:

    使用 @装饰器名 的语法在函数定义处应用装饰器,等价于:

    target_function = 装饰器名(target_function)
  • 调用装饰后的函数:

    由于装饰器返回的是一个函数对象,直接调用该函数即可。

  • 示例:

    def hi(name="yasoob"):
    return f"hi {name}"
    @decorator # 装饰器尚未定义,请继续阅读
    def target():
    return "target executed"
    def decorator(func):
    def wrapper():
    print("Before executing the decorated function")
    func()
    print("After executing the decorated function")
    return wrapper
    target = decorator(target)

    调用 target() 时,将执行装饰器应用后的 wrapper 函数,打印日志并调用原函数。

    三、带参数的装饰器

    装饰器可以接受参数,提供灵活性。这些参数通常用于自定义装饰器的行为,如日志的级别或文件路径。

    def logit(logfile='out.log'):
    def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    log_str = f" Func: {func.__name__} was called"
    print(log_str)
    with open(logfile, 'a') as f:
    f.write(log_str + '\n')
    return func(*args, **kwargs)
    return wrapper
    return decorator
    @logit(logfile='app.log')
    def foo():
    pass
    # 调用 foo() 则会记录日志到 app.log
    foo()

    四、使用 functools.wraps 维护元信息

    在装饰器应用后,原函数的元信息(如名称、文档字符串)会被替换。为了保留这些信息,可以使用 functools.wraps 装饰器:

    from functools import wraps
    def logged(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    print(f"logged: {func.__name__}")
    return func(*args, **kwargs)
    return wrapper
    @logged
    def bar(x):
    """bar函数的描述文档"""
    return x + x
    # 调用 bar 的时候,会打印 bar 的名称和文档
    bar(5)

    输出:

    logged: bar
    5 +5 = 10

    五、类装饰器

    装饰器不仅限于函数,还可以是类。类装饰器通常通过 __call__ 方法实现,能够装饰函数或其他对象。

    示例:

    class Logit:
    def __init__(self, logfile='out.log'):
    self.logfile = logfile
    def __call__(self, func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    log_str = f"{func.__name__} was called"
    print(log_str)
    with open(self.logfile, 'a') as f:
    f.write(f"{log_str}\n")
    return func(*args, **kwargs)
    return wrapper
    @Logit(logfile='func.log')
    def baz():
    pass
    baz()

    六、多层装饰器

    装饰器可以通过链式调用,逐层增加功能。

    def first_decorator(func):
    def first_wrap(*args, **kwargs):
    print("First decorator executed")
    return func(*args, **kwargs)
    return first_wrap
    def second_decorator(func):
    def second_wrap(*args, **kwargs):
    print("Second decorator executed")
    return first_decorator(func)(*args, **kwargs)
    return second_wrap
    @second_decorator
    @first_decorator
    def target():
    print("Target function")
    pass
    # 调用顺序等效于:
    # target = first_decorator(target)
    # target = second_decorator(target)
    # 但输出是:
    # 第二 decorator 执行 --> 第一个 decorator 执行 --> 目标函数执行
    # 输出顺序:
    # Second decorator executed
    # First decorator executed
    # Target function

    七、装饰器的实际应用场景

  • 日志记录: 在函数执行前后打印日志,帮助调试和监控程序运行。

  • 性能 profiling: 统计函数执行时间,分析性能瓶颈。

  • 权限控制: 检查用户身份,允许或拒绝访问特定资源。

  • 缓存机制: 在函数外层添加缓存,减少后端数据请求。

  • 异常处理: 在函数执行过程中捕捉异常,提供回滚或重试机制。

  • 连接池管理: 为数据库连接或 API 请求创建连接池,避免资源耗尽。

  • 通过这些案例,可以看出装饰器在提升代码复用性、可读性和可维护性的同时,有效支持了 OO 设计的需求。

    八、总结

    装饰器是 Python 开发中的强大工具,它允许你在不修改原函数代码的情况下,灵活添加功能和行为。掌握装饰器的使用不仅能提升代码质量,还能使你的编程效率大幅提升。建议在实际项目中,从简单的日志装饰器入手,逐步尝试复杂的场景,熟悉装饰器的灵活性和强大功能。

    上一篇:python 面试宝典--集各家之所长,乱七八糟于一体
    下一篇:详解Python的装饰器 通俗易懂的解释!

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年05月11日 05时35分25秒