一、迭代器
迭代器的特性:
迭代是Python中最强有力的特性之一,可以把迭代看成是一种处理序列中元素的方式。
可以直接作用于for循环的对象统称为可迭代对象(Iterable)。
可以被next ()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。
所有的Iterable均可以通过内置函数iter ()来转变为Iterator。
出可迭代对象的个数会报错StopIteration,是一个结束信号
迭代器的优点:
1 、迭代器提供一种不依赖于索引的取值方式,这样就可以遍历那些没有索引的对象了(字典、集合、文件)
2 、迭代器和列表比较,迭代器是惰性计算,更节约内存
迭代器的缺点:
1 、永远不能获取迭代器的长度,使用不如列表索引取值灵活
2 、一次性的,只能往后取值,不能往前,不能像索引一样取得指定位置的值
二、查看可迭代和迭代器的方法
from collections import Iterable,Iterator
s='hello'
l=[1 ,2 ,3 ]
t=(1 ,2 ,3 )
d={'a' :1 }
set1={1 ,2 ,3 ,4 }
f=open ('a.txt' )
s.__iter__()
l.__iter__()
t.__iter__()
d.__iter__()
set1.__iter__()
f.__iter__()
print (isinstance (s,Iterable))
f.__next__()
print (isinstance (f,Iterator))
三、手动访问迭代器中的元素
1、问题
我们要处理某个可迭代对象中的元素,但是基于某种原因不能也不想使用for循环。
2、解决方案
要手动访问可迭代对象中的元素,可以使用next ()函数,然后自己编写代码来捕获stopiteration异常。例如:
with open ('passwd' ,'r' ,encoding='utf8' ) as f:
while True :
try :
line=next (f)
print (line,end='' )
except StopIteration:
break
with open ('passwd' ,'r' ,encoding='utf8' ) as f:
while True :
line=next (f,None )
if line is None :
break
print (line,end='' )
大多数情况下,我们会用for 循环来访问可迭代对象中的元素,但是,偶尔也会碰到需要对底层迭代机制做更精细情况的控制。因此,了解迭代实际发生了些什么是很有必要的。for 循环也是先使用iter 方法把要循环的对象生成一个迭代器,然后去遍历这个迭代器,遍历迭代器里的每个元素
>>> items=[1 ,2 ,3 ]
>>> i=iter (items)
>>> next (i)
1
>>> next (i)
2
>>> next (i)
3
>>> next (i)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
四、生成器
生成器是一个包含yield 关键字的函数,当它被调用时,在函数中的代码不会执行,而会返回一个迭代器。每次请求一个值,就会执行生成器中的代码,直到遇到一个yield 或者return 语句,yield 语句一位着会生成一个值,return 语句一位着生成器要停止执行(不在生成任何东西,return 语句只有在一个生成器中使用时才能进行无参数调用)换句话说,生成器是由两部分组成:生成器的函数和生成器的迭代器,生成器的函数使用def 定义,包括yield 部分,生成器的迭代器是这个函数返回的部分。
def countdown(n):
print ('starting to count from' ,n)
while n>0 :
yield n
n-=1
print ('Done!' )
g=countdown(5 )
print (next (g))
print (next (g))
print (next (g))
print (next (g))
print (next (g))
#执行结果如下
starting to count from 5
5
4
3
2
1
#函数中出现了yield 语句,就会把这个函数转换成生成器。与普通的函数不同,生成器只会在响应迭代操作是才会运行。调用时需要使用next 方法才能执行,没执行一次,当遇到下一个yield 时就会停止,下次执行next 时,将从当前yield 往下执行,知道遇到一个yield
生成器的本质就是一个迭代器,同时也是一个函数,调用的方式和函数类似,yield 也相当于函数中的return
yield 和return 的区别:return 只能返回一次函数就会彻底结束,而yield 能返回多次值
yield 到底干了什么事情:
1 、yield 把函数变成生成器(迭代器),把iter 和next 方法封装在函数内部
2 、函数在暂停一及继续下一次运行时的状态是yield 保存
五、协程
from urllib.request import urlopen
def init (func ):
def wrapper (*args,**kwargs ):
res=func(*args,**kwargs)
next (res)
return res
return wrapper
@init
def get ():
while True :
url=yield
res=urlopen(url).read()
print (res)
g=get()
g.send("http://www.baidu.com" )
g.send('http://www.python.org' )
g.send('http://www.163.com' )
协程函数,是把yield 改为表达式的方式,改过send代替next 给yield 传值
e.send于next (e)的区别
1 、如果函数内yield 是表达式形式,那么必须先next (e),让生成器在第一个yield 位置处等着
2 、二者的共同之处都可以让函数在上次暂停的位置继续运行,不一样的地方在于,send在触发一下次代码的执行时,给yield 传值
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 为DeepSeek添加本地知识库
· .NET程序员AI开发基座:Microsoft.Extensions.AI
· 精选4款基于.NET开源、功能强大的通讯调试工具
· 数据不出内网:基于Ollama+OneAPI构建企业专属DeepSeek智能中台
· 大模型工具KTransformer的安装