8.9 装饰器


文章目录

  • 前言
  • 一、闭包(Closure)
    • [1.1 什么是闭包?](#1.1 什么是闭包?)
    • [1.2 闭包的工作原理](#1.2 闭包的工作原理)
    • [1.3 闭包的实际应用](#1.3 闭包的实际应用)
  • 二、装饰器(Decorator)
    • [2.1 什么是装饰器?](#2.1 什么是装饰器?)
    • [2.2 装饰器的不同形式](#2.2 装饰器的不同形式)
    • [2.3 类装饰器](#2.3 类装饰器)

前言

本文主要介绍闭包的概念以及特殊的闭包装饰器的基础知识。


一、闭包(Closure)

1.1 什么是闭包?

闭包是一个引用了外部作用域中变量的函数,即使外部函数已经执行完毕,内部函数仍然可以访问和修改这些变量。

python 复制代码
python
print("闭包的基本概念:")
print("=" * 50)

# 闭包示例
def outer_function(msg):
    """外部函数"""
    message = msg  # 自由变量
    
    def inner_function():
        """内部函数 - 闭包"""
        return f"内部函数访问: {message}"
    
    return inner_function  # 返回内部函数(闭包)

# 创建闭包
closure1 = outer_function("Hello")
closure2 = outer_function("Python")

# 使用闭包
print(f"closure1(): {closure1()}")
print(f"closure2(): {closure2()}")
print(f"closure1的类型: {type(closure1)}")
print(f"closure1.__closure__: {closure1.__closure__}")
print(f"closure1.__closure__[0].cell_contents: {closure1.__closure__[0].cell_contents}")

1.2 闭包的工作原理

python 复制代码
python
print("\n闭包的工作原理:")
print("=" * 50)

def counter_factory():
    """闭包工厂函数 - 创建计数器"""
    count = 0  # 自由变量
    
    def counter():
        """闭包函数"""
        nonlocal count  # 声明count为非局部变量
        count += 1
        return count
    
    return counter

# 创建多个独立的计数器
counter_a = counter_factory()
counter_b = counter_factory()

print("计数器A:")
for i in range(3):
    print(f"  第{i+1}次调用: {counter_a()}")

print("\n计数器B:")
for i in range(3):
    print(f"  第{i+1}次调用: {counter_b()}")

print("\n闭包的特性验证:")
print("1. 每个闭包有自己独立的状态")
print("2. 闭包可以记住并修改外部变量")
print(f"3. counter_a is counter_b: {counter_a is counter_b}")

1.3 闭包的实际应用

python 复制代码
python
print("\n闭包的实际应用:")
print("=" * 50)

# 应用1:配置管理器
def config_manager(initial_config):
    """配置管理器 - 使用闭包实现"""
    config = initial_config.copy()
    
    def get(key):
        """获取配置"""
        return config.get(key)
    
    def set(key, value):
        """设置配置"""
        config[key] = value
        return f"已设置 {key} = {value}"
    
    def show_all():
        """显示所有配置"""
        return config
    
    # 返回一个包含多个方法的字典
    return {
        'get': get,
        'set': set,
        'show': show_all
    }

# 使用配置管理器
manager = config_manager({'host': 'localhost', 'port': 8080})
print("初始配置:", manager['show']())
print("获取host:", manager['get']('host'))
print("设置新配置:", manager['set']('debug', True))
print("更新后配置:", manager['show']())

# 应用2:函数工厂
def power_factory(exponent):
    """创建幂函数 - 闭包作为函数工厂"""
    def power(base):
        return base ** exponent
    
    return power

# 创建不同的幂函数
square = power_factory(2)  # 平方函数
cube = power_factory(3)    # 立方函数
sqrt = power_factory(0.5)  # 平方根函数

print(f"\n平方函数: 5² = {square(5)}")
print(f"立方函数: 5³ = {cube(5)}")
print(f"平方根函数: √25 = {sqrt(25)}")

二、装饰器(Decorator)

2.1 什么是装饰器?

装饰器是一种特殊的闭包应用,用于修改或增强函数的功能,而不改变原函数的定义。

python 复制代码
python
print("\n装饰器基础:")
print("=" * 50)

# 最简单的装饰器
def simple_decorator(func):
    """简单装饰器"""
    def wrapper():
        print("函数执行前...")
        result = func()
        print("函数执行后...")
        return result
    return wrapper

@simple_decorator
def say_hello():
    """业务函数"""
    print("Hello, World!")
    return "执行完成"

# 使用装饰器
result = say_hello()
print(f"返回值: {result}")

2.2 装饰器的不同形式

  1. 装饰带参数的函数
python 复制代码
python
print("\n装饰带参数的函数:")
print("=" * 50)

def log_decorator(func):
    """记录函数调用的装饰器"""
    def wrapper(*args, **kwargs):
        print(f"调用函数: {func.__name__}")
        print(f"参数: args={args}, kwargs={kwargs}")
        result = func(*args, **kwargs)
        print(f"返回值: {result}")
        return result
    return wrapper

@log_decorator
def add(a, b):
    """加法函数"""
    return a + b

@log_decorator
def greet(name, greeting="Hello"):
    """问候函数"""
    return f"{greeting}, {name}!"

# 测试
print("测试add函数:")
print(f"结果: {add(3, 5)}")

print("\n测试greet函数:")
print(f"结果: {greet('Alice', greeting='Hi')}")
print(f"结果: {greet('Bob')}")
  1. 装饰器带参数
python 复制代码
python
print("\n装饰器带参数:")
print("=" * 50)

def repeat(num_times):
    """重复执行装饰器"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            results = []
            for i in range(num_times):
                print(f"第{i+1}次执行:")
                result = func(*args, **kwargs)
                results.append(result)
            return results
        return wrapper
    return decorator

@repeat(3)
def say_hi(name):
    """简单的问候函数"""
    return f"Hi, {name}!"

# 测试
print("测试重复装饰器:")
results = say_hi("Charlie")
print(f"所有结果: {results}")
  1. 多个装饰器
python 复制代码
python
print("\n多个装饰器:")
print("=" * 50)

def bold_decorator(func):
    """加粗装饰器"""
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return f"**{result}**"
    return wrapper

def italic_decorator(func):
    """斜体装饰器"""
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return f"*{result}*"
    return wrapper

# 多个装饰器的应用顺序:从下往上
@bold_decorator
@italic_decorator
def get_text():
    """获取文本"""
    return "装饰器测试"

# 相当于:bold_decorator(italic_decorator(get_text))
print("装饰后的文本:", get_text())

2.3 类装饰器

python 复制代码
python
print("\n类装饰器:")
print("=" * 50)

# 类作为装饰器
class TimerDecorator:
    """计时装饰器类"""
    
    def __init__(self, func):
        self.func = func
    
    def __call__(self, *args, **kwargs):
        import time
        start_time = time.time()
        result = self.func(*args, **kwargs)
        end_time = time.time()
        print(f"函数 {self.func.__name__} 执行时间: {end_time - start_time:.6f}秒")
        return result

@TimerDecorator
def slow_function():
    """模拟耗时函数"""
    import time
    time.sleep(0.5)
    return "任务完成"

print("测试计时装饰器:")
result = slow_function()
print(f"结果: {result}")

# 带参数的类装饰器
print("\n带参数的类装饰器:")
print("=" * 50)

class RetryDecorator:
    """重试装饰器类"""
    
    def __init__(self, max_retries=3):
        self.max_retries = max_retries
    
    def __call__(self, func):
        def wrapper(*args, **kwargs):
            for attempt in range(self.max_retries):
                try:
                    print(f"第{attempt + 1}次尝试...")
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == self.max_retries - 1:
                        raise e
                    print(f"失败: {e}, 准备重试...")
        return wrapper

@RetryDecorator(max_retries=3)
def risky_operation():
    """有风险的函数"""
    import random
    if random.random() < 0.7:
        raise ValueError("随机失败")
    return "操作成功"

print("测试重试装饰器:")
try:
    result = risky_operation()
    print(f"结果: {result}")
except Exception as e:
    print(f"最终失败: {e}")

相关推荐
耶夫斯计3 分钟前
【SQL_agent】基于LLM实现sql助理
数据库·python·sql·语言模型
vibag4 分钟前
RAG向量数据库
python·语言模型·langchain·大模型
kisshuan123964 分钟前
基于YOLO11改进的C3k2-AdditiveBlock实现命中检测与双重命中事件识别_1
python
mg6685 分钟前
0基础开发学习python工具_____用 Python + Pygame 打造绚丽烟花秀 轻松上手体验
开发语言·python·学习·pygame
nervermore99015 分钟前
2.6 测试
python
CodeOfCC17 分钟前
C++ 实现ffmpeg解析hls fmp4 EXT-X-DISCONTINUITY并支持定位
开发语言·c++·ffmpeg·音视频
ghie909017 分钟前
基于LSB匹配的隐写术MATLAB实现
开发语言·计算机视觉·matlab
Lhan.zzZ19 分钟前
Qt绘制残留问题排查与修复日志
开发语言·数据库·qt
CodeAllen嵌入式22 分钟前
Rust 正式成为 Linux 永久核心语言
linux·开发语言·rust
EZ_Python23 分钟前
告别WPS会员!用Python自制电子发票批量打印排版工具
python·自动化