Python中yield深入理解

众所周知,python中的yield有这样的用法:

def test(alist):
   for i in alist:
      yield i

这样,这个test函数就变成了一个生成器,当每次调用的时候,就会自动返回当前值。比如:

a = [1,2,3,4,5]
for i in test(a):
   print(i)

我们也可也手动遍历这个生成器:

test(a).__next__()

yield进阶

当某个函数包含了yield,就表示这个函数为一个生成器,在执行上会和普通的函数有很多不同。比如:

def test():
   print('This is a test!')
      yield 5

直接调用test函数的时候(test()),print函数是不会执行的,只有通过__next__()方法才能真正调用这个函数:test().__nexty__(). 再来一个例子:

def test():
   print('This is a test!')
   yield 5
   print('Written by Eric')
>>> t = test()	#注意这里一定要先实例化,如果直接用test().__next__()会反复返回第一次的值,不会报错
>>> t.__next__()
This is a test!
5
>>> t.__next__()	#第二次调用的时候会执行到第二个yield,由于不存在,则返回错误
written by eric
Traceback (most recent call last):
  File "<pyshell#47>", line 1, in <module>
    t.__next__()
StopIteration

send函数

__next__()函数和send()函数在某些情况下是一样的:

__next__() 等效于 send(None)

send()函数的作用是向yield表达式中传参数. 举个例子:

def test():
   print('This is a test!')
   v = yield 5
   print('The value of v is :', v)
   yield 10
   print('Written by Eric')
>>> t = test()
>>> t.send(None)	#等效于t.__next__()
This is a test!
5
>>> t.send(66)
The value of v is: 66	#v值已改变
10

值得注意的是,send更改的是在yield调用之后的值:

>>> t = test()
>>> v_temp = t.__next__()
This is a test!
>>> print(v_temp)		#此时v的值为5
5
>>> t.send(66)		#此时v的值被更改为66
The value of v is: 66
10

也就是说,我们可以利用这个send函数更改yield断点的值从而影响后面的部分,但是不影响之前的部分

原文地址:https://www.cnblogs.com/eric-nirnava/p/yield.html