具有 _iter_ 方法的对象,即为可迭代对象。
In [9]: from collections.abc import Iterable, Iterator
In [10]: class Xhz:
...: def __iter__():
...: pass
In [11]: isinstance(Xhz(), Iterable)
Out[11]: True
In [12]: isinstance(Xhz(), Iterator)
Out[12]: False
实际上 __iter__方法需要返回一个迭代器对象。
同时实现了 _iter_ 和 _next_ 方法的对象,即为迭代器对象。
In [15]: class Xhz:
...: def __iter__():
...: return self
...:
...: def __next__():
...: return 3
In [16]: isinstance(Xhz(), Iterator)
Out[16]: True
In [17]: isinstance(Xhz(), Iterable)
Out[17]: True
In [18]: a = []
In [19]: isinstance(a, Iterable)
Out[19]: True
In [20]: isinstance(a, Iterator)
Out[20]: False
内置函数 iter 的作用就是调用参数的 _iter_ 方法,获取该方法返回的迭代器对象。
内置函数 next 的作用就是调用参数迭代器的 _next_ 方法,获取返回的元素。
In [51]: a = [1, 3, 5]
In [52]: b = iter(a)
In [53]: b
Out[53]: <list_iterator at 0x1b245ba5160>
In [54]: next(b)
Out[54]: 1
In [55]: next(b)
Out[55]: 3
In [56]: next(b)
Out[56]: 5
实际上 Iterator 是 Iterable 的子类
In [21]: issubclass(Iterator, Iterable)
Out[21]: True
生成器对象其实也是一个迭代器对象
In [61]: def gen():
...: yield 3
In [62]: a = gen()
In [63]: type(a)
Out[63]: generator
In [64]: isinstance(a, Iterator)
Out[64]: True
所以可迭代对象的 _iter_ 方法可以直接返回一个生成器
In [66]: class Xhz:
...: def __iter__(self):
...: yield 3
...: yield 4
In [67]: for i in Xhz():
...: print(i)
3
4
yield from 语法用于生成器里面嵌套生成器,下面两段代码是等价的
def gen_one():
subgen = range(10)
yield from subgen
def gen_two():
subgen = range(10)
for item in subgen:
yield item
yield from 后面也可以跟可迭代对象
yield from 的另一个作用就是在调用者和内层生成器之间开辟了一条双向通道,外层调用者通过send()发送的消息可以直接到达内层生成器,内层生成器通过yield返回的数据也会直接返回给外层的调用者
return表示生成器迭代完成,通过迭代的方式并不能拿到生成器中return的返回值。
那是不是表达生成器中return值并没有意义呢?其实不是的,看下面的代码
从上面可以看出,生成器中return的值会传递给 yield from 表达式。