1. 迭代器
任何包含__iter__
和__next__
的函数将成为迭代器,而只包含__iter__
的函数则是可迭代的。
如下例子:
>>> from collections import Iterable, Iterator
>>> class Test:
... def __iter__(): pass
... def __next__(): pass
...
>>> iteration = Test()
>>> isinstance(iteration, Iterable)
True
>>> isinstance(iteration, Iterator)
True
>>> class Iter:
... def __iter__(): pass
...
>>> bb = Iter()
>>> isinstance(bb, Iterable)
True
>>> isinstance(bb, Iterator)
False
>>>
如上可以看出,当一个方法不包含__next__
,那么其只能可迭代。
斐波那契数列的迭代器写法:
>>> class Fib:
... def __init__(self, start, nextN):
... self.start = start
... self.nextN = nextN
... def __iter__(self):
... return self
... def __next__(self):
... self.start, self.nextN = self.nextN, self.start + self.nextN
... return self.start
...
>>> aa = Fib(1, 1)
>>> for i in aa:
... if i > 1000:
... print(i)
... break
...
1597
当然,迭代器的用法有很多,再比如:
>>> lines = [1, 2, 3, 4, 5, 6]
>>> out = iter(lines)
>>> next(out)
1
>>> next(out)
2
>>> next(out)
3
2. 生成器
任何包含yield方法的对象都是生成器
>>> def generator():
... for i in range(9):
... yield i
...
>>> aa = generator()
>>> aa
<generator object generator at 0x0000021D15FB7408>
>>> for i in aa:
... print(i)
...
0
1
2
3
4
5
6
7
8
>>>
当代码执行到yield语句的时候,代码将停在该处,等待下一次调用去运行yield语句后面的内容。
>>> def test_gen():
... print(1)
... yield 2
... print(3)
... yield 4
... print(5)
... yield 6
...
>>> bb = test_gen()
>>> bb
<generator object test_gen at 0x0000021D160FE750>
>>> next(bb)
1
2
>>> next(bb)
3
4
>>> next(bb)
5
6
>>> next(bb)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
最后一次调用会出现异常,这是因为生成器已经执行到了最后一个语句,后面没有内容。当然这里也可以用try except
来抓取异常。下面的是列表生成器:
>>> cc = (x for x in range(5))
>>> cc
<generator object <genexpr> at 0x0000021D16297228>
>>> for i in cc:
... print(i)
...
0
1
2
3
4
>>>
以下内容来自老男孩视频教程,这是协程的用法
from functools import wraps
def init(func):
@wraps(func)
def wrapper(*args, **kwargs):
generator = func(*args, **kwargs)
next(generator)
return generator
return wrapper
@init
def avg():
sum = 0
count = 0
average = 0
while True:
num = yield average
sum += num
count += 1
average = sum/count
>> test = avg()
>>> out = test.send(10)
>>> print(out)
10.0
>>> out = test.send(20)
>>> print(out)
15.0
>>> out = test.send(30)
>>> print(out)
20.0
网友评论