Python装饰器从入门到精通:用法详解与实战技巧

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

在这里插入图片描述

💖The Start💖点点关注,收藏不迷路💖


Python 装饰器使用详解

1. 装饰器基础概念

1.1 什么是装饰器?

装饰器本质是一个Python函数(或类),它可以在不修改原函数代码的情况下,动态地扩展函数或类的功能。其核心思想基于两点:

  1. 高阶函数:接收函数作为参数或返回函数的函数
  2. 闭包:嵌套函数能够访问外部作用域的变量

语法糖@decorator使得装饰器调用更加简洁。例如:

@log_time
def calculate():
    pass

等价于calculate = log_time(calculate)

1.2 为什么需要装饰器?

  • DRY原则:避免重复代码(如多个函数都需要日志功能)
  • 关注点分离:核心逻辑与辅助功能解耦
  • 非侵入式扩展:不改动原函数代码即可添加新功能

1.3 装饰器的简单示例

def log_call(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__} with {args}")
        return func(*args, **kwargs)
    return wrapper

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

调用add(2, 3)会输出日志信息并返回结果5


2. 装饰器的实现原理

2.1 高阶函数与闭包

def outer(msg):
    def inner():
        print(msg)  # 访问外部作用域变量
    return inner

closure = outer("Hello")
closure()  # 输出 "Hello"

2.2 无参装饰器的实现

使用functools.wraps保留原函数元信息:

from functools import wraps

def timer(func):
    @wraps(func)  # 保留__name__等属性
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"Time: {time.time()-start:.2f}s")
        return result
    return wrapper

2.3 带参数的装饰器

通过三层嵌套实现:

def repeat(n):  # 外层接收参数
    def decorator(func):  # 中层接收函数
        @wraps(func)
        def wrapper(*args, **kwargs):  # 内层实现逻辑
            for _ in range(n):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def greet():
    print("Hello")

调用greet()会输出3次"Hello"


3. 装饰器的常见应用场景

3.1 日志记录

def log(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"[LOG] {func.__name__} called")
        return func(*args, **kwargs)
    return wrapper

3.2 性能测试

import time
def timeit(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} took {time.perf_counter()-start:.4f}s")
        return result
    return wrapper

3.3 权限校验

def check_login(func):
    def wrapper(user, *args, **kwargs):
        if not user.is_authenticated:
            raise PermissionError("Login required")
        return func(user, *args, **kwargs)
    return wrapper

3.4 缓存与记忆化

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

4. 类装饰器与高级用法

4.1 类作为装饰器

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.calls = 0

    def __call__(self, *args, **kwargs):
        self.calls += 1
        print(f"Call {self.calls} of {self.func.__name__}")
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print("Hello")

4.2 多个装饰器的叠加

@log_call
@timeit
@check_login
def sensitive_operation(user):
    pass

执行顺序:log_call(timeit(check_login(sensitive_operation)))

4.3 装饰器与设计模式

  • 装饰器模式:动态添加职责
  • AOP应用:通过装饰器实现横切关注点(如日志、事务)

5. 常见问题与最佳实践

5.1 调试技巧

  • 使用print(func.__name__)检查函数名
  • inspect.signature(func)查看参数签名

5.2 性能影响

  • 每层装饰器增加一次函数调用开销
  • 避免深层嵌套(如超过3层)

5.3 替代方案

  • 上下文管理器:适合资源管理场景
with timeit_context():
    do_something()
  • 猴子补丁:运行时动态修改类/模块

6. 总结

  1. 装饰器本质是高阶函数+闭包的语法糖
  2. 典型应用:日志、性能测试、权限控制、缓存
  3. 进阶技巧:参数化装饰器、类装饰器、多装饰器组合
  4. 推荐实践:
    • 始终使用@wraps保留元信息
    • 避免过度装饰导致代码可读性下降
    • 复杂逻辑考虑使用类装饰器

通过实际项目练习,逐步掌握装饰器的灵活运用!


🔥🔥🔥道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stormsha

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值