python中yield关键字的用法
迭代(iteration)与可迭代(iterable)
使用容器时逐个获取元素的过程为迭代。
哪些类型是可迭代的
- python中的顺序类型:
list
,tuple
(元组,列表可修改元组不可修改,列表用中括号元组用小括号),string
. dict
,set
,file
.- 某类对象提供了
__iter__()
或者__getitem__()
方法.
迭代器
对迭代器不断调用next()
方法,可依次获取下一个元素,迭代器__iter__()
方法返回迭代器自身,因此迭代器也是可迭代的。
迭代器协议(iterator protocol)
一个容器提供__iter__()
方法,该方法能返回一个能逐个访问容器内所有元素的迭代器,则该容器实现了迭代器协议。
python处理for循环的过程
1 |
|
处理for循环首先调用内建函数iter(something)
,内建函数调用something.__iter__()
,返回something对应的迭代器,然后for循环会调用内建函数next()
,作用在迭代器上获取迭代器的下一个元素,并赋值给x
生成器函数(generaor function)和生成器(generator)
如果一个函数包含 yield 表达式,那么它是一个生成器函数;调用它会返回一个特殊的迭代器,称为生成器。
生成器函数被调用后,其函数体内的代码并不会立即执行,而是返回一个生成器(generator-iterator)。当返回的生成器调用成员方法时,相应的生成器函数中的代码才会执行。
“下一个yield表达式”
调用 generator.next() 时,生成器函数会从当前位置开始执行到下一个 yield 表达式。这里的「下一个」指的是执行逻辑的下一个。
1 |
|
使用 send() 方法与生成器函数通信
1 |
|
生成器函数 func 用 yield 表达式,将处理好的 x 发送给生成器的调用者;与此同时,生成器的调用者通过 send 函数,将外部信息作为生成器函数内部的 yield 表达式的值,保存在 y 当中,并参与后续的处理。
yield的好处
顺序访问容器内的前五个元素:
- way1:获取所有元素然后取前五
- way2:逐个迭代,至第五个元素
假设对于一个func(),返回值为列表,调用者对其返回值只有逐个迭代:
- 若等函数生成所有元素可能需要很长时间
- 使用yield把func()变成一个生成器函数,每次产生一个元素,可以节省开销