模拟实现一个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