Python的迭代器(iterator)和生成器(generator)

前言:
迭代的意思是重复做一些事很多次-就像循环中那样,for循环中对序列和字典进行迭代,但是实际上也能对其他的对象进行迭代:实现__iter__方法的对象。

迭代器

__iter__方法返回一个迭代器。所谓的迭代器就是具有next方法(方法不需要参数)的对象。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,迭代器没有值可以返回,就会引发一个StopIteration异常

  • 迭代器的优点:
    为什么不使用列表?如果有一个接一个地计算值得函数,那么在使用时可能是计算一个值时获取一个值-而不是通过列表一次性获取所有的值。如果有很多值,列表就会占用很多的内存,使用迭代器就很优雅。
  • 例子:
    一个实现了__iter__方法的对象是可以迭代的,一个实现了next方法的对象则是迭代器。
class Fibs:
def __init__(self):
	self.a = 0
	self.b = 1
def next(self):
	self.a,self.b = self.b,self.a
	return self.a
def __iter__(self):
	return self
  • 迭代器得到列表
    可以将迭代器转换为列表,使用list(Iterator)方法即可得到迭代的列表。

生成器

解决两层的嵌套数据结构,比如:列表的列表,a = [[1,2],[3,4],[5,6]]。按顺序得到每一个数字,则需要两个for迭代来完成。
这就是生成器的一个简单的例子,解决嵌套问题

  • 递归生成器
    如果要处理任意层嵌套该怎么办?例如可能要用树形结构表示。所以把解决方案变得更灵活,在不知道会遇到的具体层数的时候,我们可以求助于递归(recursion)。
def flatten(nested):
	try:
		for sublist in nested:
			for elemnet in flatten(sublist):
				yield element
	except TypeError:
		yield nested		
  • 通用生成器
    生成器是一个包含yield关键字的函数。当它被调用时,在函数中的代码不会被执行,而会返回一个迭代器。每次请求一个值,就会执行生成器中的代码,直到遇到一个yield或者return语句。
    生成器由两部分组成:生成器的函数和生成器的迭代器。生成器的迭代器是函数的返回部分,函数是用def定义的。
  • 生成器方法
    生成器单位新属性是在开始运行后为生成器提供值得能力
    send,throw,close方法
    外部作用域访问生成器的send方法,给生成器发送一个值,然后yield输出出来。
    throw抛出异常
    close停止生成器
  • 作用,有next方法,也可以用for来迭代生成数值,一次生成一个,可以用for 循环迭代,用list来序列化

例子:

def flatten(nested):
	try:
		for sublist in nested:
			for element in flatten(sublist):
				yield element
	except TypeError:
		yield nested
a = [[[1,214515,12,45,5],5,5,6],[14,5,45,5],[14,5,[454,4,5,[4,54,4545,[4,54,54,12]]]]]
b = flatten(a)
b.__next__()
c =list(b)
print(c)
for i in b:
    print(i)

out:[214515, 12, 45, 5, 5, 5, 6, 14, 5, 45, 5, 14, 5, 454, 4, 5, 4, 54, 4545, 4, 54, 54, 12]
上述方法中,b就是一个生成器

参考:
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个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 0x104feab40>

猜你喜欢

转载自blog.csdn.net/qq_28485501/article/details/84638377