iter, yield与enumerate的实现

模拟实现一个enumerate函数

def myEnumerate(seq, start=0):
    results = []
    n = start
    for i in seq:
        results.append((n, i))
    return results

返回一个list, 如果list数据过多,则占用内存太大。而迭代器每次只需要很小的内存。再往下看迭代器。

迭代器

内建函数iter()可以生成一个iterator迭代器。相比list来说,iterator不需要很大的内存空间。
迭代器通过next()来遍历元素,并且完成遍历时抛出StopIteration()异常。

it = iter(range(5))
print it.next()         # 0
print it.next()         # 1
print it.next()         # 2
print it.next()         # 3
print it.next()         # 4

print it.next()         # StopIteration()

可以用for循环对迭代器进行遍历

it = iter(range(5))
for i in it:
    print i

print it.next()         # StopIteration()

遍历完成时,调用it.next(),抛出StopIteration()异常。可以看出for循环调用的是next()方法。就像下边这样。

while True:
    try:
        print it.next()
    except StopIteration:
        break

用迭代器改进enumerate的实现

一个类只要实现了__iter__与next()方法, 便可以进行迭代。

class myEnumerate:
    def __init__(self, seq, start=0):
        self.seq = seq
        self.start = start
        self.n = 0

    def __iter__(self):
        return self

    def next(self):
        if self.n == len(self.seq):
            raise StopIteration()
        item = self.seq[self.n]
        index = self.start
        self.n += 1
        self.start += 1
        return index, item

使用迭代器解决了空间占用的问题,不过代码也太繁琐了,一点没有python风格。

yield

于是,简洁的代码便来了。一个可迭代的并且简洁的简洁的方案。使用next()方法会依次返回元素,并且越界时报StopIteration异常。

def myEnumerate(seq, start=0):
    n = start
    for i in seq:
        yield n, i
        n += 1

it = myEnumerate(range(5))
print it.next()         # (0, 0)
print it.next()         # (1, 1)
print it.next()         # (2, 2)
print it.next()         # (3, 3)
print it.next()         # (4, 4)
print it.next()         # StopIteration
posted @ 2015-10-24 22:28  山月水风  阅读(1166)  评论(0编辑  收藏  举报