day 13 迭代器 和 生成器
一。迭代器
字符串,列表,元组,字典,集合都可以被for循环,说明他们都是可迭代的。
for example:
from collections import Iterable
li = [2,3,4,6]
print(isinstance(li,Iterable))
2.思考:for是如何进行迭代的
print(dir(可迭代对象))
如果可迭代对象中有iter方法,就是可迭代的
print(li.__iter__())
3.迭代器(iterator)
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
for循环,能便利一个可迭代对象
4.将可迭代对象转化为迭代器(可迭代对象。__iter__())
内部使用__next__方法,一个一个取值。
加了异常处理功能,取值到底后自动停止
用while循环模拟for循环:
li = [1,3,4,6]
li_iter = li.__iter__()
while True:
try:
item = li_iter.__next__()
print(item)
except Exception:
break
5.思考?有了for循环,为什么还要用迭代器
for循环可以便利有序的可迭代对象,但是不可以便利无序的可迭代对象
所以我们要使用 可迭代器(iterator)
如此,这就是无所不能的for循环,最重要的一点,转化成迭代器,在循环时,同一时刻在内存中只出现一条数据,极大限度的节省了内存~(最主要因素)
二。生成器
有哪些可迭代的内部生成器(map,filter,enumerate,zip)
.1初始生成器
我们知道的迭代器有两种:一种是调用方法(系统内置迭代器和迭代对象)直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。
Python中提供的生成器:
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
(
生成器Generator:
本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
特点:惰性运算,开发者自定义
)
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
def generate(): print(666) print(222) content = yield 1 print(content) print(000) yield 2 g = generate() g.__next__() g.send('hello') #g.__next__()
2.2 生成器函数
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
import time
def genrator_fun1():
a = 1
print('现在定义了a变量')
yield a
b = 2
print('现在又定义了b变量')
yield b
g1 = genrator_fun1()
print('g1 : ',g1) #打印g1可以发现g1就是一个生成器
print('-'*20) #我是华丽的分割线
print(next(g1))
time.sleep(1) #sleep一秒看清执行过程
print(next(g1))
初识生成器函数
forexample
假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。
def produce():
"""生产衣服"""
for i in range(2000000):
yield "生产了第%s件衣服"%i
product_g = produce()
print(product_g.__next__()) #要一件衣服
print(product_g.__next__()) #再要一件衣服
print(product_g.__next__()) #再要一件衣服
num = 0
for i in product_g: #要一批衣服,比如5件
print(i)
num +=1
if num == 5:
break
send()方法:
#send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一yield的位置传递一个数据
#使用send的注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个yield不能接受外部的值
三,列表推导式和生成器表达式
三,列表推导式和生成器表达式
l = [i for i in range(10)] print(l) l1 = ['选项%s'%i for i in range(10)] print(l1)
1.把列表解析的[]换成()得到的就是生成器表达式
2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:
sum(x ** 2 for x in range(4))


浙公网安备 33010602011771号