首先我们先来看一下列表生成式,这能让我们更快的理解生成器
列表生成式
a = [x for x in range(10)]
#中括号为一个列表,在列表中的含义为:将循环中的x输出作为a列表的元素
def f(n):
return n**3
a=[f(x) for x in range(10)]
#循环中输出的x可以作为一个参数输入函数中, 这时f(x)的结果集将作为a列表的元素
生成器(generator object)
平时执行一个循环读取文件时,通常会把所有这个文件的内容全部存放到内存中,极大的占用和浪费内存空间,生成器的用法就是把这个对象拿到,但是并不取其中的内容值。自然也就不用把全部内容存放到内存中,在需要取到时再去取,每读取下一次时Python的垃圾回收机制就把上一次的内存回收,这样就极大的节省了内存,但是需要注意的是必须从头到尾一个一个顺序读取。
在循环中我们学习了for,但是可以并没有真正的理解。
for i in iter:#这里明确的说明了,in的对象必须是一个可迭代对象
什么是可迭代对象呢?如果内部有__iter__方法的就可以认为是一个迭代器;比如:列表、元组、字典、字符串
创建生成器两种方式
s =(x*2 for x in range(10))
#这种方式类似于列表生成式,返回的s为一个对象
def foo():
print('ok')
yield 1
print('ok2')
yield 2
g=foo() #这个G是生成器
print(g)
#在这种方式中,只要有yield这个关键字就是一个生成器对象 ,这里的g和上面的s为同一个对象
生成器的方法:
next(生成器对象) 生成一个值,再次调用生成下一个值
注意:生成器在创建的时候已经决定了能计算出值的个数,调用next次数超过这个值就会报StopIteration错误
send()方法
f().send(None)等价于next(f());send方法可以给通过yield关键字创建的生成器中传参数。
def bar():
count=yield 1
print(count)
yield 2
b=bar()
print(next(b))
# b.send(None)
ret=b.send('传入的参数')
print(ret)
首先把函数加载到内存,因为有关键字yield就认为他是一个生成器,所以在b=bar()时,不会执行函数中的输出,而是在调用next方法时把yield后的内容"1"返回打印出来,在下一行执行时通过send把参数传进去赋给count,并打印直到遇到第二个yield关键字把2返回执行结束
注意:第一次send前如果没有next,只能传一个send(None);
迭代器
生成器都是迭代器,迭代器不一定是生成器
什么是迭代器呢?满足迭代器协议就是迭代器;一下两个为迭代器协议
1、内部有next方法
2、内部有iter()方法
for 循环内部三件事
1,调用可迭代对象的iter方法返回一个迭代器对象
2,不断调用迭代器对象的next方法
3,处理StopIteration
领取专属 10元无门槛券
私享最新 技术干货