less than 1 minute read

yield

yield是实现生成器的关键。一个函数中使用了yield,这个函数就被称为生成器。

def demo(n):
    for i in range(n):
        yield i

d = demo(n)     # generator

调用这个函数不会执行,而是返回一个iterable对象,然后通过以下几个重要的方法去处理这个对象。

next(generator)

当调用next()方法时,程序开始执行。当走到yield时停下,将yield之后的值返回。当下一个next()方法到来时,程序接着从上一次等待的地方继续运行。

定义一个简单的生成器

def demo(n):
    for i in range(n):
        yield i

调用next()方法

>>> d = demo(5)
>>> next(d)
0
>>> next(d)
1
>>> next(d)
2
......

可以看到next()的返回值就是yield后跟的变量。如果yield后不跟任何变量,则返回None

generator.send(value)

send(value)方法将value传递给yield表达式的返回值,并且将该值返回。

将上面的生成器修改一下

def demo(n):
    for i in range(n):
        temp = yield i
        print(temp)

调用send()方法

>>> d = demo(5)
>>> next(d)
0
>>> next(d)
None
1
>>> d.send(100)
100
2
>>> next(d)
None
3
......

我们将yield i表达式赋值给了temp变量,当调用send()方法时,传递的值赋值给了temp

也即是说:next()的返回值是yield后的值,send()的返回值是它本身传递的参数值,并且该值还会赋值给yield语句的结果

generator.throw(Error)

在生成器中抛出异常,返回下一个yield的值或者StopIteration

依旧使用上面的例子

>>> d = demo(5)
>>> next(d)
0
>>> next(d)
None
1
>>> d.throw(StopIteration)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "\path\to\demo.py", line 3, in demo
    temp = yield i
StopIteration
>>> next(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
......

当调用throw()后,触发异常,迭代中断,后续的next()都只会得到一个StopIteration异常

能触发StopIteration异常的操作有:

  1. 迭代终止时。包括捕获异常,迭代完成。再次调用next()时将抛出异常
  2. 手动调用close()关闭生成器函数
  3. 执行过程中遇到return关键字,将直接抛出异常,如果return某一具体的值,该值为异常的说明 ```python def demo(n): for i in range(n): yield i return ‘description for StopIteration’

d = demo(2) print(next(d))

0

print(next(d))

Traceback (most recent call last):

File “", line 1, in

StopIteration: desc

```

yield from

Tags:

Updated: