Python 进阶之迭代器, 生成器

2019-01-08  本文已影响0人  不会忘的名字

一.迭代器(iterator)

1.__iter__ 得到一个迭代器。迭代器的__iter__()返回自身
2.__next__ 返回迭代器下一个值
3.如果容器中没有更多元素, 则抛出 StopIteration 异常
4.Python2中没有 __next__(), 而是 next()

实现了__iter__方法,但是没有实现__next__方法的对象.__iter__会把自身转变为一个可迭代对象.这样的话就可以用for循环去遍历它.
str/ bytes/ list/ dict/ tuple/set 都是可迭代对象, 自身不是迭代器.

例1.使用迭代器,实现原生的range功能.

class Range:
    def __init__(self, start, stop=None, step=1):
        if stop is None:
            self.start = 0
            self.stop = start
        else:
            self.start = start
            self.stop = stop
        self.step = step

    def __iter__(self):
        return self

    def __next__(self):
        # 每次循环返回当前的值.
        if self.start < self.stop:
            # 更新self.start
            res = self.start
            self.start = self.start + self.step
            return res
        else:
            raise StopIteration()


for i in Range(10):
    print(i)  # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

例2:使用迭代器,实现原生的randint功能.

import random

class Randomint:
    def __init__(self, start, end, times):
        self.start = start
        self.end = end
        self.times = times

    def __iter__(self):
        return self

    def __next__(self):
        if self.times > 0:
            self.times -= 1
            return random.randint(self.start, self.end)
        else:
            raise StopIteration()


for i in Randomint(1, 50, 10):
    print(i)  # 14, 35, 49, 29, 30, 14, 48, 25, 49, 41

二.生成器(generator)

生成器是一种特殊的迭代器, 不需要自定义 __iter____next__

例3.分别使用迭代器和生成器实现斐波那契数列

使用迭代器实现斐波那契数列

class Fab:
    def __init__(self, max_iter):
        self.prev = 0
        self.curr = 1
        self.max_iter = max_iter

    def __iter__(self):
        return self

    def __next__(self):
        # 判断有没有超出最大迭代次数
        if self.max_iter > 0:
            self.max_iter -= 1
            res = self.curr
            # 更新当前值和前一个值
            self.curr, self.prev = self.curr + self.prev, self.curr
            return res
        else:
            raise StopIteration()

使用生成器实现斐波那契数列

def fab(max_iter):
    curr = 1
    prev = 0
    while max_iter > 0:
        res = curr
        curr, prev = curr + prev, curr
        max_iter -= 1
        yield res

节省内存
惰性求值 (惰性求值思想来自于 Lisp 语言)

分三部分:生成值的表达式, 循环主体, 过滤条件表达式
列表: [i * 3 for i in range(5) if i % 2 == 0]
字典: {i: i + 3 for i in range(5)}
集合: {i for i in range(5)}

上一篇下一篇

猜你喜欢

热点阅读