美文网首页
Python 迭代器和生成器

Python 迭代器和生成器

作者: 陈忠俊 | 来源:发表于2019-08-26 22:25 被阅读0次

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

相关文章

网友评论

      本文标题:Python 迭代器和生成器

      本文链接:https://www.haomeiwen.com/subject/wmrjectx.html