一、生成器(Generators)

1. 基本概念

生成器是一种特殊的迭代器,通过延迟计算按需生成值,避免一次性加载全部数据到内存。生成器的核心是 yield 关键字,它允许函数在返回一个值后暂停执行,下次调用时从暂停处继续。

2. 创建方式
  • 生成器函数:使用 yield 关键字定义。
def countdown(n):
    while n > 0:
        yield n
        n -= 1
# 使用生成器
for num in countdown(3):
    print(num)  # 输出 3 2 1
  • 生成器表达式:类似列表推导式,但用圆括号。
squares = (x**2 for x in range(5))
print(next(squares))  # 输出 0
3. 核心特性
  • 惰性求值:仅在需要时生成值,适合处理大文件或无限序列(如斐波那契数列)。
  • 状态保存:每次 yield 会保留当前函数状态(局部变量、执行位置)。
  • 单次遍历:生成器只能遍历一次,耗尽后需重新创建。
4. 高级用法
  • send() 方法:向生成器发送数据。
def accumulator():
    total = 0
    while True:
        value = yield total
        total += value
gen = accumulator()
next(gen)        # 初始化
print(gen.send(10))  # 输出 10
  • 异常处理:通过 throw() 注入异常。

应用场景:逐行读取大文件、实时数据流处理、生成无限序列。


二、装饰器(Decorators)

1. 基本概念

装饰器是修改其他函数行为的函数,通过闭包实现。本质是将原函数替换为增强功能的新函数。

2. 创建方式
  • 函数装饰器
def timer(func):
    from time import time
    def wrapper(*args, **kwargs):
        start = time()
        result = func(*args, **kwargs)
        end = time()
        print(f"{func.__name__}耗时:{end - start}秒")
        return result
    return wrapper

@timer
def my_func():
    time.sleep(1)
my_func()  # 输出执行时间
  • 类装饰器:通过实现 __call__ 方法。
class Logger:
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        print(f"调用函数:{self.func.__name__}")
        return self.func(*args, **kwargs)
@Logger
def say_hello():
    print("Hello")
3. 核心特性
  • 参数传递:支持装饰器自身带参数。
def repeat(n=3):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                func(*args, **kwargs)
            return
        return wrapper
    return decorator
  • 装饰器链:多个装饰器按从内到外的顺序执行。
  • 保留元信息:使用 @wraps(func) 避免函数名、文档被覆盖。
4. 常用场景
  • 日志记录:跟踪函数调用和返回值。
def log(func):
    def wrapper(*args):
        print(f"调用函数:{func.__name__}")
        return func(*args)
    return wrapper
  • 权限校验:验证用户权限后执行函数。
  • 缓存结果:使用 @lru_cache 加速重复计算。

三、实际案例

生成器案例:逐行读取大文件
def read_large_file(file_path):
    with open(file_path, 'r') as f:
        for line in f:
            yield line.strip()
# 使用
for line in read_large_file("data.txt"):
    process(line)  # 逐行处理,避免内存溢出
装饰器案例:权限校验
def check_admin(func):
    def wrapper(user, *args):
        if user.is_admin:
            return func(user, *args)
        else:
            raise PermissionError("无权限操作")
    return wrapper

@check_admin
def delete_user(user):
    print("用户已删除")