迭代器与生成器

2019-10-31  本文已影响0人  魔曦帝天

迭代(iteration)与可迭代(iterable)

迭代是一种操作;可迭代是对象的一种特性。
我们可以从一个对象中,逐个地获取元素,那么我们就说这个对象是「可迭代的」。

迭代器

迭代器是一种对象
迭代器抽象的是一个「数据流」,是只允许迭代一次的对象。对迭代器不断调用 next() 方法,则可以依次获取下一个元素;当迭代器中没有元素时,调用 next() 方法会抛出 StopIteration 异常。迭代器的 __iter__() 方法返回迭代器自身;因此迭代器也是可迭代的。

迭代器协议(iterator protocol)

Python 中的迭代器协议和 Python 中的 for 循环是紧密相连的。

# iterator protocol and for loop
for x in something:
    print(x)
Python 处理 for 循环时,首先会调用内建函数 iter(something),它实际上会调用 something.__iter__(),返回 something 对应的迭代器。而后,for 循环会调用内建函数 next(),作用在迭代器上,获取迭代器的下一个元素,并赋值给 x。此后,Python 才开始执行循环体。

for循环内部操作

for循环中,会自动调用 iter()将我们要迭代的对象转化为可迭代对象,每次循环都会调用 .next() 方法获取新元素,当引发StopIteration错误的时候自动退出循环,这就for循环的内部操作。

Python 中的顺序类型,都是可迭代的(list, tuple, string)。其余包括 dict, set, file 也是可迭代的。对于用户自己实现的类型,如果提供了 iter() 或者 getitem() 方法,那么该类的对象也是可迭代的。

生成器、yield 表达式

调用过程

yield的核心在于冻结函数,一旦遇到,冻结这个函数;而return在于结束函数,一旦遇到,返回结果,函数整个退出,下次调用时重新开始执行。

生成器就是每次调用的时候返回一个对象,而不是一次性在内存中创建,从而达到节约内存的作用。

而生成器靠yield关键字实现,生成器的编写类似于函数,只不过将函数的return改成了yield:

生成器函数(generator function)和生成器(generator)

生成器函数是一种特殊的函数;生成器则是特殊的迭代器。
如果一个函数包含 yield 表达式,那么它是一个生成器函数
调用它会返回一个特殊的迭代器,称为生成器。
def func():
    return 1

def gen():
    yield 1

print(type(func))   # <class 'function'>
print(type(gen))    # <class 'function'>

print(type(func())) # <class 'int'>
print(type(gen()))  # <class 'generator'>
生成器 gen 看起来和普通的函数没有太大区别。仅只是将 return 换成了 yield。
用 type() 函数打印二者的类型也能发现,func 和 gen 都是函数。
二者的返回值的类型就不同了。
func() 是一个 int 类型的对象;而 gen() 则是一个迭代器对象。

与普通函数的区别

生成器函数被调用后,其函数体内的代码并不会立即执行,
而是返回一个生成器(generator-iterator)。
当返回的生成器调用成员方法时,相应的生成器函数中的代码才会执行
上一篇下一篇

猜你喜欢

热点阅读