广告
您当前的位置: 首页 >  技术 >  Python

Python 深入浅出:装饰器原理与实战应用

作者:CoderWang 时间:2026-06-27 阅读数:8人阅读

在 Python 编程中,装饰器(Decorator)是一种极其强大且优雅的语法。它允许我们在不修改原有函数代码的前提下,动态地为函数或类添加额外的功能。

无论是进行日志记录、性能测试、权限校验,还是实现缓存机制,装饰器都是 Python 开发者的必备利器。本文将带您由浅入深,彻底掌握 Python 装饰器的底层原理与实战应用。


一、 预备知识:函数是“一等公民”

要理解装饰器,首先必须理解 Python 中函数的设计哲学:函数是一等公民(First-Class Citizens)。 这意味着在 Python 中: 1. 函数可以被赋值给变量。 2. 函数可以作为参数传递给另一个函数。 3. 函数可以作为另一个函数的返回值

例如:

def greet(name):
    return f"Hello, {name}"

# 1. 赋值给变量
say_hello = greet
print(say_hello("Alice"))  # 输出: Hello, Alice

# 2. 作为参数与返回值(闭包)
def run_func(func, val):
    return func(val)

print(run_func(greet, "Bob"))  # 输出: Hello, Bob

二、 装饰器的本质:闭包的语法糖

装饰器本质上是一个接收函数作为参数,并返回一个新函数的闭包。

1. 手动实现一个最简单的装饰器

假设我们有一个函数,我们想在它执行前后打印日志:

def my_decorator(func):
    def wrapper():
        print("--- 准备执行函数 ---")
        func()
        print("--- 函数执行结束 ---")
    return wrapper

def say_hello():
    print("Hello World!")

# 手动进行包装
decorated_func = my_decorator(say_hello)
decorated_func()

2. 引入语法糖 @

Python 提供了 @ 符号作为装饰器的语法糖,省去了手动包装的步骤。以下代码与上面的手动包装完全等价:

@my_decorator
def say_hello():
    print("Hello World!")

say_hello()

当我们写下 @my_decorator 时,Python 解释器在后台自动执行了:say_hello = my_decorator(say_hello)


三、 进阶:处理带参数和返回值的函数

实际开发中,被装饰的函数往往带有参数,并且有返回值。为了让装饰器能够通用,我们需要在内部的 wrapper 函数中使用 *args**kwargs,并返回原函数的执行结果。

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"开始执行: {func.__name__},参数: {args}, {kwargs}")
        result = func(*args, **kwargs) # 接收原函数的返回值
        print(f"执行结束: {func.__name__}")
        return result # 返回该结果
    return wrapper

@log_decorator
def add(a, b):
    return a + b

sum_result = add(5, 7)
print("计算结果:", sum_result)

四、 黄金法则:使用 functools.wraps

当我们使用装饰器后,原函数的元数据(如函数名 __name__ 和文档字符串 __doc__)会被内部的 wrapper 函数覆盖:

print(add.__name__)  # 输出: wrapper,而不是 add!

这会导致调试和自动化文档生成时出现混乱。为了解决这个问题,Python 提供了 functools.wraps 装饰器,专门用于将原函数的元数据拷贝给 wrapper

from functools import wraps

def better_log_decorator(func):
    @wraps(func)  # 拷贝原函数的元数据
    def wrapper(*args, **kwargs):
        print(f"执行中...")
        return func(*args, **kwargs)
    return wrapper

五、 实战案例:编写一个耗时统计装饰器

让我们编写一个在生产环境中非常实用的“函数执行耗时统计”装饰器:

import time
from functools import wraps

def time_it(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        elapsed = end_time - start_time
        print(f"🔥 性能分析 -> 函数 [{func.__name__}] 执行耗时: {elapsed:.6f} 秒")
        return result
    return wrapper

# 测试该装饰器
@time_it
def compute_heavy_task():
    return sum(i * i for i in range(1000000))

compute_heavy_task()

六、 总结

Python 装饰器是遵循“开放封闭原则”(对扩展开放,对修改封闭)的经典设计。熟练使用装饰器和 functools.wraps,能帮助我们大幅减少重复代码,保持核心业务逻辑的纯净度。

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。

评论交流 (0)

正在加载评论...
头像

CoderWang

当你还撑不起你的梦想时,就要去奋斗。如果缘分安排我们相遇,请不要让她擦肩和过。我们一起奋斗!

微信