Iteration迭代器
1、我们首先以for loop为目标,for loop的实现机理很简单,就是一个while循环,等待抛出StopIteration的异常来退出循环,如下例:
test_list_two = ["123", "456", "789"]
for item in test_list_two:
print(item)
# 模拟for loop
# for loop 的大致原理
# a for loop takes an iterator and iterates over it using next()
test_iter = iter(test_list_two)
while True:
try:
print(next(test_iter))
except StopIteration:
break
执行结果
123
456
789
123
456
789
可以看到,执行的结果是一模一样的,可以这样说,for loop就是拿到了iterator,然后无限循环,用next(iterator)来对迭代器进行移动,等到迭代到末尾,就会抛出StopIteration
的一场,这时在推出。
下面的例子能够更好的理解迭代器
# When we reach the end and there is no more data to be returned,
# it will raise StopIteration.
test_list = [1, 2, 3, 4]
test_iter = iter(test_list)
print(next(test_iter))
print(next(test_iter))
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
执行结果
1
2
3
4
Traceback (most recent call last):
File "D:test1.py", line 10, in <module>
print(test_iter.__next__())
StopIteration
2、知道了迭代器的原理,我们手动写一个可以迭代的对象
这个对象只需要对__iter__(),__next__()
函数进行更改即可。__iter__()
返回的对象要能够调用.__next__()
方法,__next__()
方法要有最终推出,抛出StopIteration
的异常。
# next和iter也只不过是调用的实例的self.__next__,和self.__iter__而已
class TestIterator:
def __init__(self, max):
self.max = max
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n < self.max:
result = 3 ** self.n
self.n += 1
return result
else:
raise StopIteration
a = TestIterator(4)
for item in a:
print(item)
执行结果
1
3
9
27
3、不过要小心,因为循环使用的无限续循环,迭代对象很有可能永远了无法耗尽
如下面的例子,int()是可迭代的,然后iter()方法里面第二个参数是哨兵
意思就是如果next值不是第二个参数,就继续迭代
test_iter = iter(int, 1)
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
print(test_iter.__next__())
执行结果
0
0
0
0
0
0
0
0
0
4、我们也可以手动让for循环无线循环,只要raise StopIteration就行了
class TestIteratorTwo:
def __iter__(self):
self.num = 1
return self
def __next__(self):
num = self.num
print(num)
self.num += 2
return num
# 这样就无限循环了,看吧,即使是for循环里面pass了,也是有输出的
for item in TestIteratorTwo():
pass
执行结果
···
181425
181427
181429
181431
181433
181435
···