https://zhuanlan.zhihu.com/p/84548471
https://www.runoob.com/python3/python3-iterator-generator.html
https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/part/1.html
迭代:
迭代是Python最强大的功能之一,是访问集合元素的一种方式。⽤简单的话讲,它就是从某个地方(比如⼀个列表)取出⼀个元素的过程。当我们使⽤⼀ 个循环来遍历某个东西时,这个过程本⾝就叫迭代。
迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。迭代器不仅要实现__iter__方法,还需要实现__next__方法字符串,列表或元组对象都可用于创建迭代器。
可迭代对象Python中任意的对象,只要它定义了可以返回⼀个迭代器的__iter__方法,或者定义了 可以支持下标索引的__getitem__⽅法,那么它就是⼀个可迭代对象。
实现了__iter__方法,但是它没有实现__next__,这也是判定迭代器和其他可迭代对象的关键之处,可以看一下通过next访问上述示例中可迭代对象X会报错,
next(X)
# 输出
TypeError: 'set' object is not an iterator
通过Python内置的iter函数能够轻松把可迭代对象转化为迭代器,下面来看一个例子,
X = [1,2,3,4,5]
print(type(X))
Y = iter(X)
print(type(Y))
print(next(Y))
print(next(Y))
print(next(Y))
# 输出
<class 'list'>
<class 'list_iterator'>
1
2
3
生成器
生成器也是迭代器的一种,但是你只能迭代它们一次.原因很简单,因为它们不是全部存在内存里, 它们只在要调用的时候在内存里生成。生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。在Python中一个函数可以用yiled替代return返回值,当你调用函数的时候,函数里的代码并没有运行.函数仅仅返回生成器对象,这就是它最微妙的地方举个例子对比一下,
def generator(array):
for i in array:
yield(i)
gen = generator([1,2,3,4,5])
print(type(gen))
# 输出
<class 'generator'>
这里有个关于生成器的创建问题面试官有考:
问: 将列表生成式中**[]改成()** 之后数据结构是否改变?
答案:是,从列表变为生成器
>>> L = [x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x0000028F8B774200>
在这里这个例子好像没什么用,不过当你的函数要返回一个非常大的集合并且你希望只读一次的话,那么它就非常的方便了.
通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算。
控制迭代器的穷尽
StopIteration
StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
创建迭代器
把一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next() 。
如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 init(), 它会在对象初始化的时候执行。
更多内容查阅:Python3 面向对象
iter() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
next() 方法(Python 2 里是 next())会返回下一个迭代器对象。
创建一个返回数字的迭代器,初始值为 1,逐步递增 1:
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))