1 生成器概念
生成器是一个特殊的迭代器(迭代器的抽象层级更高)
所以,生成器拥有迭代器的特性:1.惰性计算,节省内存。2.更够记录状态,并通过next()函数,访问下一个状态。3.具备可迭代特性。
2 生成器的的创建
(1)使用生成器表达式,示例代码如下:
# l = [i for i in range(1, 1000) if i % 2 ==0]
# 直接生成一个列表
l = (i for i in range(1, 1000) if i % 2 ==0)
# 直接生成一个生成器
print(next(l))
print(next(l))
print(l.__next__())
>>> 2
>>> 4
>>> 6
(2)使用生成器函数
函数中包含yield语句,这个函数执行结果就是“生成器”,示例代码如下:
yield,可以去阻断当前的函数运行,使用next()函数或next()方法,都会让函数继续执行,执行到下一个yield语句并把yield后的值当做状态值返回,函数到此处暂停。
特别说明:不使用next()或next()方法,函数不会执行,一行都不会执行,只会返回一个生成器。
def test():
print("xxx")
yield 1
print("a")
yield 2
print("b")
yield 3
print("c")
yield 4
print("d")
g = test()
print(g)
print(next(g))
print(next(g))
print(next(g))
>>> <generator object test at 0x000000002134d5>
>>> xxx
>>> 1
>>> a
>>> 2
>>> b
>>> 3
当生成器内的yield语句运行完之后,再一直使用next()或next()方法,就会报错StopIteration
也可以使用for in 来遍历,这种方法可以把最后一个yield下面的语句也运行出来。
def test():
print("xxx")
yield 1
print("a")
yield 2
print("b")
yield 3
print("c")
g = test()
for i in g:
print(i)
>>> xxx
>>> 1
>>> a
>>> 2
>>> b
>>> 3
>>> c
3 send()方法
(1)send()方法有一个参数,指的是上一次被挂起的yield语句返回值
(2)相比于.next(),send()可以额外的给yield传值
(3)注意第一次使用,t.send(None)
next()方法只是执行,不会传入值
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.__next__())
print(g.__next__())
>>> xxx
>>> 1
>>> None # res1的值为None
>>> 2
send()方法给res1传入了值ooo,send()执行的位置在yield2处,但是它传入的值给到了上一次被挂起的yield1处。
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.__next__())
print(g.send("ooo"))
>>> xxx
>>> 1
>>> ooo # res1的值为ooo
>>> 2
直接执行send()传值操作会报错,因为它只给上一个yield挂起位置传值。
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.send("ooo"))
>>> TypeError: can't send non-None value to a just-started generator
g.send(None) <=> g.next(),我们可以使用send(None),运行第一个yield,到第二个再使用send()传值就可以了。
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.send(None))
print(g.send("ooo"))
>>> xxx
>>> 1
>>> ooo
>>> 2
4 close()方法关闭生成器
使用close()方法可以直接关闭生成器,再次调用生成器,会报错StopIteration
def test():
yield 1
print("a")
yield 2
print("b")
yield 3
print("c")
g = test()
print(g.__next__())
print(g.__next__())
g.close()
print(g.__next__())
>>> 1
>>> a
>>> 2
>>> StopIteration
5 注意事项:
如果碰到return,生成器会直接终止,抛出StopIteration异常提示
def test():
yield 1
print("a")
yield 2
print("b")
return 10
yield 3
print("c")
g = test()
print(g.__next__())
print(g.__next__())
print(g.__next__())
>>> 1
>>> a
>>> 2
>>> 3
>>> StopIteration:10
生成器只会遍历一次,再次遍历需要重新创建,比如再次使用g = test()