基本用法
yield的作用主要是创建生成器 generator, 生成器也是用于迭代的,想对于普通迭代对象如list 来说,生成器不会事先生成所有的集合元素,而是边迭代边生成,占用内存更少。
如果一个函数里不是用return来返回数据,而是用yield来返回数据,那么这个函数就是生成器,注意,yield关键字只能用在函数体里面
def generator():
for i in range(1000000):
yield i
def itertor():
return range(1000000)
g=generator()
for i in g: #迭代生成器
print(i)
for i in itertor(): #迭代list
print(i)
上面generator()函数就是使用了yield的生成器,它和itertor()函数的区别就是它不会真的生成一个长度为一百万的序列,而只是记录了这一百万个数据的生成方式,所以它占用内存很少。而itertor()函数使用的使用的range(1000000)则真的会生成一百万个元素在列表里(注:python2里range是直接生成元素,python3里range则也变成了生成器)。
send方法
在迭代生成器的时候,每次遇到yield i 会返回i, 然后迭代器函数就在yield的地方暂停运行,线程切换到调用处,在调用处进入下一次for 循环时,线程又切回到生成器函数上次yield的地方继续运行。其实在线程切回到yield的时候可以传递参数给生成器
def generator2():
num = []
while True:
new = yield
num.append(new)
print(num)
g2=generator2()
next(g2) # 首先将生成器的代码运行到yield处,也叫激活生成器
g2.send(1) # 这里继续执行上次暂停的生成器,并传递了参数1 给 new
g2.send(2) # 传递参数2给new
#输出
[1]
[1, 2]
之前的生成器是通过for 循环遍历的,其实for 循环的本质就是不停的next(generator)输出下一个元素,直到遍历结束。上面的例子就是使用next函数来调用的,在generator2里yield空值,然后线程跳到了g2.send(1),send的作用就是让线程带了一个参数回到生成器里面,这个参数传给了new,然后生成器继续执行。
yield from用法
yield from 基本的用法是代替for 循环,yield一个可迭代对象
def generator3()
num = [1,2,3,4,5]
#for i in num:
# yield i
yield from num
for x in generator3():
print(x)
上面的yield from 就是简化了for循环的yield语句。
yield from 还可以接受生成器的返回值,我们知道生成器是通过yield来返回值的,return的值是无法通过for 迭代生成器来获得的,var = yield from 可以获取return
def f():
for i in range(2):
yield i
return 3
def g():
a = yield from f()
print('a = {}'.format(a))
for item in g():
print(item)
#输出
0
1
a = 3
yield from 还有一个高级的用法,就是协程,后面介绍
网友评论