什么是装饰器?

装饰器是Python中一个强大的特性,它允许我们在不修改原函数代码的情况下,给函数添加新的功能。简单来说,装饰器就是一个函数,它接收一个函数作为参数,并返回一个新的函数。

基础示例:计时装饰器

让我们从一个最常用的例子开始——计算函数执行时间:

import time
from functools import wraps

def timer(func):
    """计算函数执行时间的装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} 执行时间: {end_time - start_time:.4f}秒")
        return result
    return wrapper

@timer
def slow_function():
    """一个慢函数"""
    time.sleep(1)
    return "完成!"

# 使用
result = slow_function()
# 输出: slow_function 执行时间: 1.0012秒

带参数的装饰器

有时候我们需要给装饰器传递参数,这时需要再包一层:

def repeat(times=3):
    """重复执行函数的装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(times):
                result = func(*args, **kwargs)
                results.append(result)
            return results
        return wrapper
    return decorator

@repeat(times=3)
def greet(name):
    return f"你好, {name}!"

# 使用
messages = greet("张三")
print(messages)
# 输出: ['你好, 张三!', '你好, 张三!', '你好, 张三!']

实用装饰器:缓存结果

使用装饰器实现函数结果缓存,提升性能:

def cache(func):
    """简单的缓存装饰器"""
    cached_results = {}
    
    @wraps(func)
    def wrapper(*args):
        if args in cached_results:
            print(f"从缓存返回: {args}")
            return cached_results[args]
        
        result = func(*args)
        cached_results[args] = result
        return result
    return wrapper

@cache
def fibonacci(n):
    """计算斐波那契数列"""
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 使用
print(fibonacci(10))  # 第一次计算
print(fibonacci(10))  # 从缓存返回

类装饰器

装饰器不仅可以是函数,还可以是类:

class Counter:
    """统计函数调用次数的装饰器"""
    def __init__(self, func):
        self.func = func
        self.count = 0
    
    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"{self.func.__name__} 被调用了 {self.count} 次")
        return self.func(*args, **kwargs)

@Counter
def say_hello():
    print("Hello!")

# 使用
say_hello()  # say_hello 被调用了 1 次
say_hello()  # say_hello 被调用了 2 次
say_hello()  # say_hello 被调用了 3 次

实战:日志装饰器

一个实用的日志装饰器,记录函数调用信息:

import logging
from datetime import datetime

logging.basicConfig(level=logging.INFO)

def log_calls(func):
    """记录函数调用的装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 记录调用前
        logging.info(f"调用函数: {func.__name__}")
        logging.info(f"参数: args={args}, kwargs={kwargs}")
        logging.info(f"时间: {datetime.now()}")
        
        try:
            result = func(*args, **kwargs)
            logging.info(f"返回值: {result}")
            return result
        except Exception as e:
            logging.error(f"异常: {e}")
            raise
    return wrapper

@log_calls
def divide(a, b):
    """除法函数"""
    return a / b

# 使用
result = divide(10, 2)
# divide(10, 0)  # 会记录异常

总结

装饰器是Python中非常优雅的特性,主要应用场景包括:

  1. 性能监控:计时、内存使用统计
  2. 缓存:避免重复计算
  3. 权限检查:验证用户权限
  4. 日志记录:自动记录函数调用
  5. 重试机制:自动重试失败的操作

掌握装饰器,能让你的Python代码更加优雅和可维护!


本文介绍了Python装饰器的基础用法和实用示例,希望对你有帮助!

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]