当前位置: 首页 > news >正文

七、Python高级特性:迭代器、生成器与装饰器

🔄 ​一、迭代器协议:可迭代对象的本质

“迭代器是Python序列化访问的通用接口——将复杂的遍历逻辑简化为统一的next()调用。”

1. 可迭代对象 vs 迭代器
类型特征核心方法
可迭代对象可用for循环遍历__iter__()
迭代器通过next()逐步获取数据__iter__() + __next__()
# 自定义迭代器:生成斐波那契数列
class Fibonacci:def __init__(self, n):self.n = nself.a, self.b = 0, 1self.count = 0def __iter__(self):return selfdef __next__(self):if self.count >= self.n:raise StopIteration  # 终止迭代value = self.aself.a, self.b = self.b, self.a + self.bself.count += 1return value# 使用迭代器
fib = Fibonacci(5)
for num in fib:print(num)  # 输出:0, 1, 1, 2, 3
2. 内置迭代工具
  • ​**iter()next()函数**​:
    numbers = [1, 2, 3]
    it = iter(numbers)
    print(next(it))  # 1
    print(next(it))  # 2
  • ​**enumerate()索引迭代**​:
    for idx, char in enumerate("Python"):print(f"{idx}:{char}")  # 0:P, 1:y...
  • ​**zip()并行迭代**​:
    names = ["Alice", "Bob"]
    scores = [85, 92]
    for name, score in zip(names, scores):print(f"{name}: {score}")

🌟 ​二、生成器:惰性计算的魔法

1. 生成器函数(yield)​
def countdown(n):while n > 0:yield n  # 暂停并返回当前值n -= 1gen = countdown(3)
print(next(gen))  # 3
print(next(gen))  # 2

优势​:

  • 内存高效:逐项生成数据,不预存完整序列
  • 无限序列:可表示无限流(如传感器数据流)
2. 生成器表达式
squares = (x**2 for x in range(5))  # 生成器表达式
print(list(squares))  # [0, 1, 4, 9, 16]

对比列表推导式​:

  • 列表推导式:[x**2 for x in range(5)] → 立即生成完整列表
  • 生成器表达式:(x**2 for x in range(5) → 惰性计算
3. 协程应用(双向通信)​
def coroutine():while True:received = yield  # 接收外部send()的值print(f"Received: {received}")c = coroutine()
next(c)  # 启动生成器(到yield处暂停)
c.send("Hello")  # 输出:Received: Hello

🎭 ​三、装饰器:元编程的轻量级武器

1. 基础装饰器原理
def logger(func):def wrapper(*args, ​**kwargs):print(f"调用函数: {func.__name__}")return func(*args, ​**kwargs)return wrapper@logger
def add(a, b):return a + bprint(add(2, 3))  # 输出:调用函数: add → 5

执行流程​:
add = logger(add) → 实际调用wrapper函数

2. 带参数的装饰器
def repeat(n):  # 装饰器工厂def decorator(func):def wrapper(*args, ​**kwargs):for _ in range(n):func(*args, ​**kwargs)return wrapperreturn decorator@repeat(3)
def say_hello():print("Hello!")say_hello()  # 输出3次"Hello!"
3. 类装饰器
class Timer:def __init__(self, func):self.func = funcdef __call__(self, *args, ​**kwargs):start = time.time()result = self.func(*args, ​**kwargs)print(f"耗时: {time.time() - start:.4f}s")return result@Timer
def heavy_task():time.sleep(2)heavy_task()  # 输出:耗时: 2.0003s

⚡ ​四、综合实战:高效数据处理管道

1. 流式日志分析器
def log_reader(file):"""生成器:逐行读取日志"""with open(file) as f:for line in f:yield line.strip()def filter_errors(logs):"""过滤错误日志"""for log in logs:if "ERROR" in log:yield logdef count_logs(logs):"""统计日志数量"""count = 0for log in logs:count += 1yield count, log# 构建处理管道
logs = log_reader("app.log")
error_logs = filter_errors(logs)
counted_errors = count_logs(error_logs)for count, error in counted_errors:print(f"错误 #{count}: {error}")
2. 函数性能监控系统
import functools
import timedef performance_monitor(prefix=""):def decorator(func):@functools.wraps(func)  # 保留原函数属性def wrapper(*args, ​**kwargs):start = time.perf_counter()result = func(*args, ​**kwargs)elapsed = time.perf_counter() - startprint(f"{prefix}{func.__name__} 耗时: {elapsed:.6f}s")return resultreturn wrapperreturn decorator@performance_monitor("API:")
def fetch_data(url):time.sleep(0.5)return f"Data from {url}"fetch_data("https://api.example.com")  # 输出:API:fetch_data 耗时: 0.500012s

🧠 ​五、避坑指南与性能优化

  1. 迭代器陷阱

    • 单次消费​:迭代器只能遍历一次(it = iter(data)后需重新初始化)
    • 无限迭代​:生成器需明确终止条件(避免while True无退出)
  2. 装饰器副作用

    • 元信息丢失​:用@functools.wraps保留__name__等属性
    • 调试困难​:多层装饰时用inspect模块追踪调用栈
  3. 性能优化技巧

    • 生成器管道​:替代中间列表减少内存占用
    • LRU缓存​:对纯函数用@functools.lru_cache缓存结果
    • 异步生成器​:async for处理I/O密集型任务

💎 ​结语:编程范式的融合艺术

迭代器统一了遍历接口,生成器实现了惰性之美,装饰器解耦了横切关注点——三者共同构建了Python高效与优雅的基石。建议在PyCharm中创建advanced_features.py,尝试:

  1. 用生成器实现素数无限序列
  2. 为数据库查询函数添加重试装饰器
  3. 组合迭代器与装饰器构建ETL数据管道

下篇预告​:
《Python异步编程:协程与并发实战》——揭秘如何用asyncio处理高并发I/O!

🔗 ​关联知识​:

  • 回顾前篇:面向对象编程:从类到元类
  • 官方文档:生成器 | 装饰器
  • 拓展阅读:Real Python协程指南

【本文是Python入门系列第7篇】
: 迭代器协议:__iter____next__
: 生成器:yield魔法与协程应用
: 装饰器:函数增强与元编程
: 实战案例:日志处理与性能监控
: 性能优化:惰性计算与缓存策略

相关文章:

  • 智能实验室革命:Deepoc大模型驱动全自动化科研新生态
  • 前端 E2E 测试实践:打造稳定 Web 应用的利器!
  • echarts柱状图要给柱子顶部加一个顶的写法方案
  • 在反向代理环境下精准获取客户端真实 IP 的最佳实践
  • 每日八股文补充2网络篇
  • GESP C++ 五级真题(2024年12月)题解
  • Shell 流程控制
  • 什么是Sanity Testing?和冒烟测试的区别?
  • Kotlin中协程挂起函数的本质
  • 数据结构学习——二叉树
  • PCIE中基于地址的路由
  • IPV6概述
  • 【Android知识点】面试版
  • 1. 配置OSPF智能定时器
  • Docker 入门教程(三):镜像操作命令
  • 【菜狗的记录】模糊聚类最大树、图神经网络、大模型量化——20250627
  • Ubuntu安装Docker部署Python Flask Web应用
  • 【RAG面试题】如何获取准确的语义表示
  • 自动登录脚本神器-Mac电脑实现自动登录堡垒机并自动输入账号密码跳转不同机器环境
  • GitHub Actions与AWS OIDC实现安全的ECR/ECS自动化部署