通过官方文档让你看的懂看的对,真正了解迭代器、生成器、可迭代对象
迭代器、生成器、可迭代对象、迭代器协议
先说好这篇文章是根据python3.6 写出来的,其他语言博主不清楚是否和Python一样
- 迭代器协议在Python3.6的文档(4.5. Iterator Types)中定义如下:实现 _iter_(),_next_()两中方法的容器(可以理解为类)称之为迭代器,其中_iter_() 方法返回的必须还是迭代器
- 迭代器:实现迭代器协议的对象就叫迭代器
- 生成器:生成器可以理解为 生成迭代器的工厂,一种工厂函数(没找到好的定义),生成器的返回结果在Python中被称为
生成器迭代器
也是一种迭代器,也可以说迭代器包含着生成器
,在Python3.6的文档(6.2.9. Yield expressions)中的原话是:When a generator function is called, it returns an iterator known as a generator.翻译一下大概是:当一个生成器函数被调用的时候,它返回一个称为生成器的迭代器(生成器迭代器)。 - 可迭代对象:能生成迭代器的对象,通俗的将也就是实现_iter_()方法的对象,以字符串举例 字符串可以进行迭代,但不能使用next(str),是因为字符串是可迭代对象而不是迭代器,也就是说字符串对象只实现了_iter_()方法而没有_next_()方法
三者之间的关系如下:
Demo 实现python3.6中的range方法
这里只是效果等同,不是复现
- 构建迭代器类:
class DemoIterator(object):
def __init__(self, i, end):
self.__i = i
self.__end = end
def __next__(self):
if self.__i > self.__end:
raise StopIteration()
self.__i += 1
return self.__i - 1
def __iter__(self):
# 由于这个方法要返回可迭代对象,他自己刚好就是
return self
- 构建可迭代对象类
class DemoRange:
def __init__(self, start, end):
self.__start = start
self.__end = end
def __iter__(self):
return DemoIterator(self.__start, self.__end)
if __name__ == '__main__':
c = iter(DemoRange(0, 3))
print("is_iterator:", isinstance(c, abc.Iterable))
# 为了便于理解迭代器的工作流程下面用while 循环代替 for i in xx
# for i in DemoRange(0, 3):
# print(i)
# 可以看到for 循环为我们做了很多事情
while True:
try:
print(next(c))
except StopIteration:
break
这里之所以不使用一个类实现是参考了《流畅的Python》一书中特意指出的不要 反设计
输出如下:
改进:使用生成器代替上述代码中的迭代器类
class DemoRange:
def __init__(self, start, end):
self.__start = start
self.__end = end
def __iter__(self):
while True:
if self.__start < self.__end:
yield self.__start
self.__start += 1
else:
raise StopIteration()
# return DemoIterator(self.__start, self.__end)
这里可以看到省略了很多代码
总结
- 生成器和迭代器之间的区别还有生成器有 send(), throw(),close()等方法,见生成器方法这些方法刚好可以构成流程控制,比如
使用 next() 激活一个生成器函数,通过何时使用send()控制生成器返回迭代器,next()得到结果来实现流程控制
,而流程控制刚好又是协程的核心思想,于是各种yield实现协程的教程应运而生。而在早期版本中通常使用装饰器激活协程…扯远了
转载注明出处