Python.二.(三).迭代器和生成器 Python 中迭代器的概念核心结论可迭代对象Iterable实现__iter__迭代器Iterator实现__iter____next__。迭代器是带状态的惰性求值对象 。我们来看一个from collections import Iterable print(isinstance(abcddddd, Iterable)) # str是否可迭代 print(isinstance([1,2,3,4,5,6], Iterable)) # list是否可迭代 print(isinstance(12345678, Iterable)) # 整数是否可迭代 -------------结果如下---------------- True True False当对所有的可迭代对象调用 dir() 方法时会发现他们都实现了 iter 方法。这样就可以通过 iter(object) 来返回一个迭代器。x [1, 2, 3] y iter(x) print(type(x)) print(type(y)) ------------结果如下------------ class list class list_iterator可以看到调用iter()之后变成了一个list_iterator的对象。可以发现增加了一个__next__方法。所有实现了__iter__和__next__两个方法的对象都是迭代器。迭代器是带状态的对象它会记录当前迭代所在的位置以方便下次迭代的时候获取正确的元素。__iter__返回迭代器自身__next__返回容器中的下一个值如果容器中没有更多元素了则抛出Stoplteration异常。x [1, 2, 3] y iter(x) print(next(y)) print(next(y)) print(next(y)) print(next(y)) ----------结果如下---------- 1 2 3 Traceback (most recent call last): File /Users/Desktop/test.py, line 6, in module print(next(y)) StopIteration如何判断对象是否是迭代器和判断是否是可迭代对象的方法差不多只要把 Iterable 换成 Iterator。Python的for循环本质上就是通过不断调用next()函数实现的举个栗子下面的代码先将可迭代对象转化为Iterator再去迭代。这样可以节省对内存因为迭代器只有在我们调用 next() 才会实际计算下一个值。可迭代对象是迭代器、生成器和装饰器的基础。简单来说可以使用for来循环遍历的对象就是可迭代对象。比如常见的list、set和dict一、两个概念Iterable ≠ Iterator概念协议作用可迭代对象Iterable__iter__能被for遍历迭代器Iterator__iter____next__带状态逐个产出元素from collections.abc import Iterable, Iterator x [1, 2, 3] isinstance(x, Iterable) # True list 是可迭代对象 isinstance(x, Iterator) # False 但不是迭代器 y iter(x) # iter() 把 Iterable 转为 Iterator isinstance(y, Iterator) # True补充有__getitem__且接受整数索引的对象即使没有__iter__也能被iter()使用旧协议向后兼容。二、迭代器的工作机制迭代器是带状态的对象记录当前迭代位置。__iter__返回自身__next__返回下一个值无元素时抛出StopIterationx [1, 2, 3] y iter(x) print(next(y)) # 1 print(next(y)) # 2 print(next(y)) # 3 print(next(y)) # StopIteration三、for 循环的本质Python 的for循环等价于以下代码# for elem in x: 等价于 ↓ _iter iter(x) while True: try: elem next(_iter) # 循环体 except StopIteration: break先调用iter()转为迭代器再不断next()捕获StopIteration退出。迭代器惰性求值——只有调用next()才计算下一个值节省内存。四、生成器与迭代器的关系生成器Generator是创建迭代器的便捷方式自动实现迭代器协议# 生成器函数用 yield def counter(start0): while True: yield start start 1 # 生成器表达式 squares (x**2 for x in range(10))生成器本身就是迭代器无需手写__iter__/__next__。五、itertools 实用工具from itertools import count, cycle, chain, islice # count: 无限计数器 c count(start13) next(c) # 13 next(c) # 14 # chain: 拼接多个可迭代对象 list(chain([1, 2], [3, 4])) # [1, 2, 3, 4] # islice: 切片用于无限迭代器 list(islice(count(1), 5)) # [1, 2, 3, 4, 5]一句话记忆Iterable 是能被遍历的Iterator 是带状态逐个产出的。iter()把前者变成后者for循环 iter()while next()StopIteration。生成器是创建迭代器的语法糖。. Python 中生成器的相关知识结论生成器是惰性求值的迭代器用yield暂停执行并产出值。现代协程已不再依赖 generator而是async/await核心价值不必一次性生成所有数据按需计算节省内存。# 列表推导式定义即生成占满内存 a [x * x for x in range(10)] # 生成器表达式惰性求值几乎不占内存 b (x * x for x in range(10))生成器函数用yield代替return遇到yield暂停并返回值下次next()从断点恢复def spam(): yield first yield second yield third for x in spam(): print(x) # first / second / third调用函数不执行函数体而是返回生成器对象。yield记录执行位置下次从断点继续。send()— 双向通信生成器不仅能产出值还能接收外部传入的值def echo(): while True: received yield # 接收 send() 传入的值 print(fgot: {received}) gen echo() next(gen) # 先启动到 yield 处暂停必须 gen.send(hello) # got: hello gen.send(world) # got: worldyield from— 委托生成器PEP 380def sub_gen(): yield 1 yield 2 def main_gen(): yield 0 yield from sub_gen() # 直接委托给子生成器 yield 3 list(main_gen()) # [0, 1, 2, 3]yield from建立主生成器与子生成器的双向通道是async/await的前身。协程的现代演进⚠️阶段机制状态早期generator yield已废弃PEP 380yield from仍可用于生成器委托PEP 492async/await✅ 当前标准# 现代协程写法 import asyncio async def fetch_data(): await asyncio.sleep(1) return data❌ 协程通过 generator 实现是过时说法。现代协程用async/awaitasyncio.coroutine装饰器已在 3.12 移除。. Python 中装饰器的相关知识结论装饰器本质是接收函数、返回函数的高阶函数用语法糖实现隐式包装。必须加functools.wraps保留元信息 从手动包装到语法糖的演进import logging from functools import wraps def use_log(func): wraps(func) # ✅ 保留原函数 __name__、__doc__ 等元信息 def wrapper(*args, **kwargs): logging.warning(%s is running % func.__name__) return func(*args, **kwargs) return wrapper use_log # 等价于 bar use_log(bar) def bar(): I am bar print(I am bar) bar() # WARNING:root:bar is running # I am bar bar.__name__ # bar不加 wraps 会变成 wrapper带参数的装饰器— 三层嵌套def repeat(times): # 第 1 层接收参数 def decorator(func): # 第 2 层接收被装饰函数 wraps(func) def wrapper(*args, **kwargs): for _ in range(times): result func(*args, **kwargs) return result return wrapper return decorator repeat(3) # 先调用 repeat(3) 返回 decorator再用 decorator 装饰 def greet(): print(hi) greet() # 打印 3 次 hi类装饰器— 装饰器不一定是函数也可以是类class CountCalls: def __init__(self, func): self.func func self.count 0 def __call__(self, *args, **kwargs): self.count 1 print(fcall #{self.count}) return self.func(*args, **kwargs) CountCalls def say_hi(): print(hi)多个装饰器的执行顺序decorator_a # 先装饰外层 decorator_b # 后装饰内层 def func(): pass # 等价于func decorator_a(decorator_b(func)) # 执行时a 先进入b 后进入b 先退出a 后退出洋葱模型常见应用场景日志记录、性能计时、权限校验、缓存functools.lru_cache、重试机制。一句话记忆生成器用yield做惰性求值协程已转向async/await装饰器必须加wraps记住接收函数返回函数这一个本质带参装饰器只是多套一层。

相关新闻

最新新闻

北京创业扶持机构哪家入驻流程服务省心:【博亚信诚】流程简便

北京创业扶持机构哪家入驻流程服务省心:【博亚信诚】流程简便

开篇语:随着北京城市产业升级步伐不断加快,大量初创企业、成长型科技企业纷纷计划落地北京各大产业园区,选址入驻成为企业发展路上的首要环节,很多企业负责人都会产生疑问,北京创业扶持机构哪家入驻流程服务省心。【博…

2026/8/7 8:31:44
深入解析STM32 HAL库GPIO初始化:从时钟使能到配置优化

深入解析STM32 HAL库GPIO初始化:从时钟使能到配置优化

1. 从“知其然”到“知其所以然”:为什么需要深入分析MX_GPIO_Init? 很多刚开始接触STM32 HAL库的朋友,对 MX_GPIO_Init() 这个函数的态度,大概就是“CubeMX生成的,直接用就行”。确实,在STM32CubeMX这个…

2026/8/7 8:31:44
SAP Fiori Contact Data 设计详解,从 CDS 语义建模到联系人信息在 Fiori UI 中的呈现

SAP Fiori Contact Data 设计详解,从 CDS 语义建模到联系人信息在 Fiori UI 中的呈现

做 SAP Fiori 项目时,有一类字段几乎每个业务系统都会都非常普通。数据库里可能只是几个 CHAR、STRING 或日期类型字段,CDS View 里也不过是 FirstName、LastName、PhoneNumber、EmailAddress 之类的普通元素。可是一旦进入 SAP Fiori 的 metadata-driven UI 世界,事情就发生…

2026/8/7 8:31:44
Python实现命令行3D魔方渲染器:从零掌握图形学与矩阵变换

Python实现命令行3D魔方渲染器:从零掌握图形学与矩阵变换

如果你正在学习Python,想找一个既有趣又能综合运用多种编程概念的项目,那么用Python实现一个3D魔方命令行渲染器绝对值得一试。这听起来可能有点“复古”——在图形界面无处不在的今天,为什么还要在命令行里折腾3D?但恰恰是这个看…

2026/8/7 8:31:44
相位检测自动对焦(PDAF)原理详解:从核心机制到手机与相机实战应用

相位检测自动对焦(PDAF)原理详解:从核心机制到手机与相机实战应用

1. 从“拉风箱”到“快准狠”:为什么相位对焦改变了摄影 如果你用过十年前的数码相机或者早期的智能手机拍照,一定对那个“拉风箱”的过程记忆犹新——半按快门后,镜头会前后伸缩几次,伴随着“滋滋”的马达声,画面从模…

2026/8/7 8:31:44
天猫改价系统:驱动级硬件伪装,平台检测维度再全也查不出

天猫改价系统:驱动级硬件伪装,平台检测维度再全也查不出

天猫改价系统:驱动级硬件伪装,平台检测维度再全也查不出 每次有人问我店群怎么做大,我就一句话:天猫的极速自动改价,是店群运营中最耗人力也最容易出错的环节。 电商价格战是分钟级的。竞品降价了你5分钟内不跟&…

2026/8/7 8:26:43