python 全栈开发,Day13(迭代器,生成器)
一、迭代器
python 一切皆对象
能被for循环的对象就是可迭代对象
可迭代对象: str,list,tuple,dict,set,range
迭代器: f1文件句柄
dir打印该对象的所有操作方法
1 2 | s = 'python' print ( dir (s)) |
执行输出:
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
什么是可迭代对象:内部含有__iter__方法的对象就叫做可迭代对象
可迭代对象就遵循可迭代协议。
如何判断 两种方式
第一种:
1 2 | s = 'python' print ( '__iter__' in dir (s)) |
执行输出:
True
第二种:
1 2 3 | from collections import Iterable l = [ 1 , 2 , 3 , 4 ] print ( isinstance (l, Iterable)) |
执行输出:
True
1 2 3 4 | from collections import Iterable l = [ 1 , 2 , 3 , 4 ] print ( type (l)) print ( isinstance (l, list )) |
执行输出:
<class 'list'>
True
type只能判断是什么类型
isinstance判断方面更广,不仅能判断类型,还能判断是否可迭代
迭代器
可迭代对象转化成迭代器:可迭代对象.__iter__() --->迭代器
迭代器不仅含有__iter__,还含有__next__。遵循迭代器协议。
1 2 3 | l1 = [ 1 , 2 , 3 ] l1_obj = l1.__iter__() # 迭代器 print (l1_obj) |
执行输出:
<list_iterator object at 0x000001987D5EB668>
表示它是一个列表迭代器对象
1 2 3 4 5 | l1 = [ 1 , 2 , 3 ] l1_obj = l1.__iter__() # 迭代器 print ( '__iter__' in dir (l1_obj)) #是否含有__iter__方法 print ( '__next__' in dir (l1)) #是否含有__next__方法 print ( '__next__' in dir (l1_obj)) |
执行输出:
True
False
True
从结果中,可以看出l1_obj是同时含有__iter__和__next__的对象,所以它是迭代器
迭代器使用__next__获取一个值
1 2 3 4 5 6 | l1 = [ 1 , 2 , 3 ] l1_obj = l1.__iter__() # 迭代器 print (l1_obj.__next__()) #获取一个元素 print (l1_obj.__next__()) print (l1_obj.__next__()) print (l1_obj.__next__()) |
执行报错:
1
Traceback (most recent call last):
2
3
File "E:/python_script/day13/迭代器.py", line 9, in <module>
print(l1_obj.__next__())
StopIteration
多取了一个,就会报错,因为列表只有3个元素
使用for循环方式
1 2 3 4 | l1 = [ 1 , 2 , 3 ] l1_obj = l1.__iter__() # 转换为迭代器 for i in l1_obj: print (i) |
执行输出:
1
2
3
for循环的内部机制,就是用__next__方法执行的。为什么没有报错呢?它内部有异常处理机制
总结:
仅含有__iter__方法的,就是可迭代对象
包含__iter__和__next__方法的,就是迭代器
判断迭代器的2种方法:
第1种:
1 2 3 | l1 = [ 1 , 2 , 3 ] l1_obj = l1.__iter__() # 转换为迭代器 print ( '__iter__' in dir (l1_obj)) |
第2种:
1 2 3 4 | l1 = [ 1 , 2 , 3 ] l1_obj = l1.__iter__() # 转换为迭代器 from collections import Iterator print ( isinstance (l1_obj, Iterator)) |
返回True,就表示它是的
迭代器的好处:
1,节省内存空间。
2,满足惰性机制。
3,不能反复取值,不可逆。
不可逆,表示,已经取过的值,不能再次取,它只能取下一个。
for处理机制
1 2 3 | l2 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] for i in l2: print (i) |
1,将可迭代对象转化成迭代器
2,内部使用__next__方法取值
3,运用了异常处理去处理报错。
迭代器最大的好处,就是节省内存
好的程序员,会在内存优化方面考虑,比如迭代器。
使用while循环,指定用__next__方法遍历列表
1 2 3 4 5 6 7 8 | l2 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] l2_obj = l2.__iter__() #1.将可迭代对象转化成迭代器 while True : try : i = l2_obj.__next__() #内部使用__next__方法取值 print (i) except Exception: #运用了异常处理去处理报错 break |
try里面的代码,出现报错,不会提示红色文字
Exception 可以接收所有报错,表示报错的时候,该怎么处理,这里直接使用breck跳出循环
面试题:
使用whlie循环去遍历一个有限对象
直接使用上述代码即可。
二、生成器
生成器:生成器本质上是迭代器
1 2 | l = [ 1 , 2 , 3 ] l.__iter__() |
#生成器的产生方式:
1,生成器函数构造。
2,生成器推导式构造。
3,数据类型的转化。
1 2 3 4 5 6 | def func1(): print ( 111 ) print ( 222 ) print ( 333 ) return 666 print (func1()) |
执行输出:
111
222
333
666
将函数转换为生成器
1 2 3 4 5 6 7 | def func1(): print ( 111 ) print ( 222 ) print ( 333 ) yield 666 g = func1() print (g) |
执行输出:
<generator object func1 at 0x000001B4C369DE60>
第一:函数中只要有yield 那他就不是一个函数,而是一个生成器
第二:g称作生成器对象。
迭代器,使用__next__取值
1 2 3 4 5 6 7 8 | def func1(): print ( 111 ) print ( 222 ) print ( 333 ) yield 666 g = func1() print (g.__next__()) print (g.__next__()) |
执行报错
一个__netxt__对应一个yield
比如生产10000套服装
一个厂商直接生产出10000套了
1 2 3 4 | def func1(): for i in range ( 1 , 10001 ): print ( 'ARMAIN服装%d套' % i) func1() |
执行输出:
...
ARMAIN服装9998套
ARMAIN服装9999套
ARMAIN服装10000套
第二个厂商,先生产出50套,给老板看
1 2 3 4 5 6 | def func1(): for i in range ( 1 , 10001 ): yield 'ARMAIN服装%d套' % i g = func1() for i in range ( 1 , 51 ): print (g.__next__()) |
执行输出:
...
ARMAIN服装48套
ARMAIN服装49套
ARMAIN服装50套
最终老板只要200套
先50套,再150套
1 2 3 4 5 6 7 8 9 | def func1(): for i in range ( 1 , 10001 ): yield 'ARMAIN服装%d套' % i g = func1() for i in range ( 1 , 51 ): print (g.__next__()) #再执行150次,注意,它是从51开始的 for j in range ( 150 ): print (g.__next__()) |
之前生产10000套的....
对于列表而言,for循环是从开始
对于生成器而言,它是有指针的,__next__一次,指针向前一次。它不能从头开始。
必须依次执行才行
生成器和迭代器的区别
迭代器: 有内置方法
生成器: 开发者自定义
send
1 2 3 4 5 6 7 8 9 10 11 12 | def generator(): print ( 123 ) content = yield 1 print ( '=======' ,content) print ( 456 ) yield g = generator() ret = g.__next__() print ( '***' ,ret) ret = g.send( 'hello' ) #send的效果和next一样 print ( '***' ,ret) |
执行输出:
123
*** 1
======= hello
456
*** None
send 获取下一个值的效果和next基本一致
只是在获取下一个值的时候,给上一yield的位置传递一个数据
使用send的注意事项
第一次使用生成器的时候 是用next获取下一个值
最后一个yield不能接受外部的值
next 和send 功能一样,都是执行一次
send可以给上一个yield赋值。
明日默写内容:
1.什么是可迭代对象,什么是迭代器
答:
内部含有__iter__方法的对象就叫做可迭代对象
内部必须有__iter__方法和__next__方法的对象,叫做迭代器
2.可迭代对象如何转化成迭代器
答:
转化成迭代器:可迭代对象.__iter__() --->迭代器
例如
1 2 | l1 = [ 1 , 2 , 3 ] l1_obj = l1.__iter__() |
3.迭代器如何取值
答:
迭代器使用__next__()方法
4.什么是生成器?如何写一个生成器?生成器怎么取值?
答:
生成器,即生成一个容器。在Python中,一边循环,一边计算的机制,称为生成器。
#生成器示例
1 2 | def fun1(): yield 1 |
生成器使用__next__()方法取值,或者for循环
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix