您的位置:首页 > 编程语言 > Python开发

python iterator总结

2016-12-09 10:04 120 查看
这篇文字翻译字这里

iterator是可以用来迭代的对象,这篇文章会介绍iterator是如何工作的,并且如何通过__iter__和__next__方法创建你自己的iterator.

python的iterator是可迭代的对象,它可以返回数据,每次一个元素。

python的iterator必须实现两个方法,__iter__()和__next__(),它们一起被称为迭代协议(iterator protocol)

一个对象是可迭代的,如果可以从它获取到一个iterator。

python大多数的内置containers都是可迭代的,例如list, tuple,string等。

它们的iter()函数(也被称为__iter__()函数)返回一个它们里面的迭代器.

通过一个Iterator来迭代

我们通过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循环. 这样方式允许我们对任何能返回iterator的对象进行迭代,例如list, string, file等.

>>> for element in my_list:
...     print(element)
...
4
7
0
3


for 循环是怎样工作的?

就像上面看到的那样, for循环可以对一个列表自动进行迭代.

实际上for循环可以迭代任何可迭代的对象. 让我们进一步看看python是是如何实现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循环创建一个迭代对象,iter_obj调用可迭代对象的iter().

有趣的是,for循环实际是一个无限的while循环.

在循环内部,它调用next()来获取下一个元素,并对这个值执行for循环的代码逻辑。当所有元素都被处理外币,会引发StopIteration异常,for循环结束。注意,任何其他的异常都会被忽略。

在python里面创建你的迭代器

python里面创建一个迭代器是很简单的. 只需要实现__iter__()和__next__()即可.

__iter__()方法返回的是迭代器对象自己. 一些初始化工作也可以放在这个方法里面.

__next__()方法必须返回序列里面的下一项,在抵达最后一个元素以后,如果继续调用这个方法,必须引发StopIteration异常.

下面这个例子展示了一个返回2的指数的迭代器类,它能返回一个用户设定的2的指数

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


也可以在for循环用

>>> for i in PowTwo(5):
...     print(i)
...
1
2
4
8
16
32

python无限迭代器

一个迭代器对象返回的项可以是无限数量的.实现这种类型的迭代器对象必须小心.下面就是一个例子.

内置函数iter()可以用两个参数来调用,第一个参数必须是可调用对象(函数),第二个是sentinal(意思是哨兵).迭代器调用这个函数直到返回的值等于sentinal的值.

>>> int()
0

>>> inf = iter(int,1)
>>> next(inf)
0
>>> next(inf)
0


可以看到int()函数总是返回0.所以对它使用iter(int,1),永远也得不到1.

我们也可以建立自己的无限迭代器.下面的迭代器理论上能反悔所有的奇数

class InfIter:
"""Infinite iterator to return all
odd numbers"""

def __iter__(self):
self.num = 1
return self

def __next__(self):
num = self.num
self.num += 2
return num


运行效果如下

>>> a = iter(InfIter())
>>> next(a)
1
>>> next(a)
3
>>> next(a)
5
>>> next(a)
7


在使用这些无限数量的迭代器的时候,要小心地给出一个种植条件.

使用迭代器的好处在于节省资源.就像上面这个例子,我们不需要保存所有的奇数就可以得到任意一个奇数.理论上,在有限的内存空间可以得到无限数量的奇数.

python里面还有一个更简单的创建迭代器的方法,使用yield产生generator,我们下篇再说.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: