Iterators是可以向上迭代的对象。在这篇博客中,我们会学习到iterator如何工作,以及如何使用__iter__和__next__方法(即class中的函数)定义你自己的iterator。
What are iterators in Python?
Iterators在Python随处可见,for循环,comprehensions,generator等等都是用它来实现的,只是表面你看不见。
在Python中,iterator仅仅就是个可以迭代的对象(object),一个可以返回数据的对象,每次返回一个元素。
从技术上来说,python iterator object必须要实现两个方法:__ iter __ () 和 __ next __() ,统称为iterator protocal。
如果我们得到了一个iterator object,我们就把这个对象称之为iterable。绝大多数内建的container都是可迭代的(iterable):list,tuple,string等等。
使用iter() 函数可以给我们返回一个iterator。
Iterating Through an Iterator in Python
我们使用 next() 函数手动迭代出一个iterator中所有的项,当到最后一个项时不会再有元素返回,它将引发 StopIteration ,看下面例子。
# define a list
my_list = [4, 7, 0, 3]
# get an iterator using iter()
my_iter = iter(my_list)
## iterate through it using next()
#prints 4
print(next(my_iter))
#prints 7
print(next(my_iter))
## next(obj) is same as obj.__next__()
#prints 0
print(my_iter.__next__())
#prints 3
print(my_iter.__next__())
## This will raise error, no items left
next(my_iter)
一个更棒的自动迭代方法你是使用for loop。如此一来,我们就可以对任何能返回iterator的对象进行迭代。比如说 list,string,file等。
>>> for element in my_list:
... print(element)
...
4
7
0
3
How for loop actually works?
在上面的例子中,for循环能自动在list中迭代。实际上,for循环可以在任何可迭代的对象上进行迭代。让我们深入看看for循环内部怎么实现的:
for element in iterable:
# do something with element
实际上实现是这样的:
# create an iterator object from that iterable
iter_obj = iter(iterable)
# infinite loop
while True:
try:
# get the next item
element = next(iter_obj)
# do something with element
except StopIteration:
# if StopIteration is raised, break from loop
break
所以在内部,for 循环创建一个iterator对象,是调用 iter() 函数完成的。有意思的是,for循环实际上一个有限的while循环。
在循环内部,它调用next()得到下一个元素,然后用这个元素执行for循环中的主体代码。当iterator中元素迭代完时,StopIteration会被触发,循环结束。需要注意的是,任何其他的异常都会被通过。
Building Your Own Iterator in Python
在python中从头构建iterator很容易,只需要实现两个方法:__iter()和__next()。
iter()方法会返回它本身的迭代器。如若需要,可以完成初始化。
next()方法必须依序返回下一个元素,直到最后一个对象,如果此时再调用__next()__则会引发StopIterator。
class PowTwo:
"""Class to implement an iterator
of powers of two"""
def __init__(self, max = 0):
self.max = max
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n <= self.max:
result = 2 ** self.n
self.n += 1
return result
else:
raise StopIteration
下面我们创建一个迭代器,如下迭代:
>>> a = PowTwo(4)
>>> i = iter(a)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
4
>>> next(i)
8
>>> next(i)
16
>>> next(i)
Traceback (most recent call last):
...
StopIteration