Python迭代器生成器

66 阅读2分钟

迭代器

迭代器与Python2.2版本后添加,他为类序列对象提供了一个可以使其进化为迭代器的接口 iter

迭代器对象内部会维持一个状态,用于记录当前迭代的状态,以方便下次迭代时提取正确的数据元素

可迭代对象内置__iter__函数,该函数将对象处理为可迭代对象

任何实现__iter____next__的对象都可看作迭代器

__iter__返回迭代器自身、__next__返回迭代的下个值

迭代器没有返回的元素,抛出StopIteration,迭代器类似于工厂模式,每次返回一个值

无限迭代器

  • 给定起点和步长,创建无限递增的迭代器
from itertools import count
count(start=...step...)
  • 有限数据对象晋升为无限迭代器
from itertools import cycle

有限迭代器

  • 将序列晋升为迭代器
iter()
  • 从一个可迭代对象范围内生成一个迭代器
from itertools import islice
islice(iterable, stop)
islice(iterable, start, stop[, step])
  • 满足条件返回,不满足条件终止生成迭代器
takewhile(predicate, iterable)
itertools.takewhile(lambda x:x!=3, [1,2,3,4,5])

自定义迭代器

要完善__iter____next__方法

  • 以斐波那契数列为例
class FBNQ:
    def __init__(self):
        self.perv = 0
        self.curr = 1
   	def  __iter__(self):
        return self
    def __next__(self):
        rt = self.curr
        self.curr += self.prev
        self.prev = value
        return value

生成器

生成器是特殊的迭代器,生成器自动实现了迭代器协议(iternext),不需要手动维护这两种方法

元组推导式

ge =  (var  for var in range(10))

该表达式可以在处理大量数据保存在序列时,比较费内存

而当前方式可以延迟生产数据,节约内存,数据只有在需要的时候才生产

yield关键字

如果在函数中出现了yield关键字,该函数将不在是普通函数,而是生成器函数

def func():
    num = 18600000000
    while True:
        if num < 18700000000:
            yield num
            num += 1
  • 注意:如果在生成器函数内部使用return、那么将直接抛出StopIteration

创建好的生成器支持如下一些操作

gen = func()
gen.close() # 手动关闭生成器函数,会使后面的生成器使用直接返回StopIteration
gen.send() # 生成器函数可以接收一个外部传入的变量,并且可以像函数处理参数一样将这个变量在运行期间进行处理并返回,在使用send函数时,第一次首先需要传入None或next函数调用的形式将生成器第一个值生产
gen.throw(ValueError) # 用来像生成器函数传入一个异常,使生成器结束
def gen():
	num = 0
	while True:
        var = yield num
        #send函数传入的值在这里
        num = var + num
g = gen()
#re = g.send(None)
re = next(g)
print(re) # 0
re = g.send(3)
print(re) # 3
re = g.send(3)
print(re) # 6