迭代器
1.1介绍
访问一个列表或元组时很平常的做法是通过下标访问例如:
lst = [1, 2, 3, 4, 5]
for i in range(len(lst)):
print lst[i]
但是除了这种方式,其实还有另外一种方式,使用迭代器:
lst = [1, 2, 3, 4, 5]
for value in lst:
print value
当然,在这里貌似迭代器并没有展现出什么优势,反倒丢失了索引,不过可以使用内建函数enumerate()找回这个索引如下例:
lst = [1, 2, 3, 4, 5]
for index, value in enumerate(lst):
print index, value
对于可以随机访问的数据结构比如元组和列表,迭代器没有优势,那么对于不能随机访问的数据结构比如字典或者set,迭代器是唯一访问元素的方式:
dic = {'a': "nice", 'b': "to", 'c': "meet", 'd': 'you'}
for (key, value) in dic.iteritems():
print key, value
事实上,dic.iteritems()返回的就是一个迭代器对象.
1.2使用
使用iter()函数可以获取迭代器对象:
lst = [1, 2, 3, 4, 5]
lst = iter(lst)
print lst
输出:<listiterator object at 0x7f4141f2b450>
使用迭代器的next()方法可以访问下一个元素:
lst = [1, 2, 3, 4, 5]
lst = iter(lst)
print lst.next()
输出:1
假如访问到最后一个元素,然后在next(),则会抛出异常:
Traceback (most recent call last):
File "test.py", line 22, in <module>
lst.next()
StopIteration
File "test.py", line 22, in <module>
lst.next()
StopIteration
实际上,python正是根据捕捉到这个异常来停止迭代.
lst = [1, 2, 3, 4, 5]
lst = iter(lst)
try:
while True:
print lst.next()
except StopIteration:
pass
实际上,在for循环中,Python将自动调用iter()获得迭代器,然后自动调用next()获取元素,而且还检查是否抛出
StopIteration异常.
1.3自定义迭代器
其实在Python中没有迭代器这个类,具有以下两个特性的类都可以成为迭代器类:
1.具有next方法,返回容器的下一个元素或者抛出StopIteration异常;
2.有__iter__方法,返回迭代器本身.
那么动手自己写一个迭代器类,实现求斐波那契数列:
class Fib(object):
"""docstring for my_iterator"""
def __init__(self, num):
super(Fib, self).__init__()
self.num = num
self.n, self.a, self.b = 0, 0, 1
def next(self):
if self.n < self.num:
result = self.b
self.a, self.b = self.b, self.a + self.b
self.n += 1
return result
raise StopIteration
def __iter__(self):
return self
def main():
for result in Fib(5):
print result
if __name__ == '__main__':
main()
补充
def test():
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l1 = [x for x in lst if x % 2 == 0]
l2 = (x for x in lst if x % 2 == 1)
print l1
print l2
def main():
test()
if __name__ == '__main__':
main()
输出:
[2, 4, 6, 8]
<generator object <genexpr> at 0x7ffaaa498c30>
<generator object <genexpr> at 0x7ffaaa498c30>
一个是列表,一个是迭代器.在代码中不同的仅仅是一个是[],一个是()