参考:https://nvie.com/posts/iterators-vs-generators/
生成器是python独有的概念,别的语言里面没有。在理解生成器之前,先理解迭代器相关的概念,包括** 容器、迭代器协议、可迭代的、 迭代器**
容器
容器是保存元素的数据结构,支持成员资格测试。是存在于内存中的数据结构,通常也在内存中保存它们的所有值。在Python中,一些典型的容器例子是
- list, deque, …
- set, frozensets, …
- dict, defaultdict, OrderedDict, Counter, …
- tuple, namedtuple, …
- str
从技术上讲,当可以询问对象是否包含某个元素时,它就是一个容器。可以对列表、集或元组等执行此类成员资格测试:
>>> assert 1 in [1, 2, 3] # lists
>>> assert 4 not in [1, 2, 3]
>>> assert 1 in {1, 2, 3} # sets
>>> assert 4 not in {1, 2, 3}
>>> assert 1 in (1, 2, 3) # tuples
>>> assert 4 not in (1, 2, 3)
# 字典数据需要检查key
>>> d = {1: 'foo', 2: 'bar', 3: 'qux'}
>>> assert 1 in d
>>> assert 4 not in d
>>> assert 'foo' not in d # 'foo' is not a _key_ in the dict
# 字符串 也可以检查子串是否存在
>>> s = 'foobar'
>>> assert 'b' in s
>>> assert 'x' not in s
>>> assert 'foo' in s # a string "contains" all its substrings
**大多数的容器都是可迭代对象,可以使用某种方式访问容器中的每一个元素。但并不是所有容器都是可迭代的,比如 Bloom filter **
text = 'bairuichangyangna' # 容器
text_iter = iter(text) # 迭代器
print(next(text_iter))
迭代器
- 迭代器协议:对象需要提供next方法,要么返回迭代中的下一项,要么引起一个StopIteration异常,以终止迭代
- 可迭代对象:实现了迭代器协议的对象
协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(如for 循环, sun, min,max函数等)均使用迭代器协议访问对象
- 迭代器:实现了__iter__和__next__方法的对象都称为迭代器,迭代器是一个有状态的对象,在调用next() 的时候返回下一个值,如果容器中没有更多元素了,则抛出StopIteration异常。
可迭代对象
容器 与 可迭代对象 区别*:*
可迭代对象是可以返回迭代器(目的是返回其所有元素)的任何对象,不一定是数据结构。
可迭代 和 迭代器 的区别
迭代器
迭代器是一个有状态的辅助对象,当在其上调用next()时,它将产生下一个值。 因此,具有__next __()方法的任何对象都是迭代器。 它如何产生值是无关紧要的。
所以迭代器就是值工厂。每次向它询问“下一个”值时,它都知道如何计算它,因为它持有内部状态。
迭代器的例子不胜枚举。所有itertools函数都返回迭代器。
自定义迭代器* 生成 $Fibonacci$ 数列*
生成器
生成器是一种特殊的迭代器,任何生成器均是迭代器(反过来不是),但是生成器不需要像迭代器一样实现__iter__和__next__方法,只需要使用关键字yield或者生成器表达式就可以。
生成器允许编写类似于上面斐波那契序列迭代器示例的迭代器,但语法简洁,避免编写带有iter()和next()方法的类。
Python使用生成器对延迟操作提供了支持,延迟操作是指在需要的时候才产生结果,而不是立即产生结果。
Python有两种生成器提供方法:
生成器函数:
用生成器函数产生斐波那契数列:
fib 就是一个生成器函数,调用该函数时返回对象就是生成器 ga,这个生成器对象的行为和迭代器是非常相似的,可以用在 for 循环等场景中