Python-生成器、迭代器

  1. 生成器、迭代器
    1. 生成器
    2. 迭代器

生成器、迭代器

生成器

不存在元组生成式,元组是不可变类型的对象,无法再代码中动态的创建元组对象。但是,将列表生成式的[]改成(),程序并不会报错,而是得到一个generator(生成器)对象。为了查看生成器对应的所有元素,有两种方式:
1、调用next()内置函数,每次调用都返回生成器的下一个元素,直到抛出异常StopIteration为止

>>> gen = (x for x in range(10))
>>> gen
<generator object <genexpr> at 0x7f98dff3b840>
>>>
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
3
>>> next(gen)
4
>>> next(gen)
5
>>> next(gen)
6
>>> next(gen)
7
>>> next(gen)
8
>>> next(gen)
9
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration                              # 生成器不会循环调用
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

2、使用for-in循环进行迭代,这样就不需要关心StopIteration异常了

>>> gen = (x for x in range(10))
>>> for i in gen:
...     print(i)
...
0
1
2
3
4
5
6
7
8
9

生成器中保存的并不是其对应的所有元素,而是如何推算出所有元素的算法。将生成器用于for-in语句时,元素是在循环过程中不断被推算出来的。将生成器作为内置函数next()的实参时,返回的下一个元素也是在调用函数时被推算出来的,因此生成器是惰性推算,也就是说,只有当用到生成器中的某个元素时,才会临时进行推算,而并不会提前退算出来。

如果需要创建一个元素个数较大的容器,就可以考虑使用生成器,从而节省大量的空间。

上面我们使用类似生成式的语法得到的生成器被称为生成器表达式。此外,当推算的算法比较复杂时,我们还可以使用生成器函数得到生成器。
生成器函数中通过关键字yield返回推算出来的元素。生成器函数与普通函数的区别在于:当调用内置函数next()或使用for-in语句进行迭代时,执行完yield语句就会将生成器函数挂起,下次会从挂起的地方继续执行。

>>> a, b, c = 1, 2, 3
>>>
>>> def func():
...     print(a)
...     yield a
...     print(b)
...     yield b
...     print(c)
...     yield c
...
>>>
>>> f = func()
>>>
>>> next(f)
1
1
>>> next(f)
2
2
>>> next(f)
3
3
>>> next(f)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

斐波那契数列

#!/usr/bin/python3

def fib(num):
    n, a, b = 0, 0, 1
    while n < num:
#        print(b)
        yield b
        a, b = b, a + b
        n += 1

迭代器

可迭代对象和迭代器并不一样
可迭代对象
可以用于for-in语句的对象被称为可迭代(Iterable)对象,例如:range、列表、元组、字符串、字典、集合、生成器都是可迭代对象。
可以调用内置函数isinstance()判断一个对象是否是可迭代对象。标准库模块collections中的类Iterable用于表示可迭代对象。

>>> from collections import Iterable
__main__:1: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
>>> isinstance([1, 2, 3], Iterable)
True
>>>

迭代器
如果一个可迭代对象可以作为内置函数next()的实参,从而支持惰性推算,那么该对象就被称为迭代器对象(Iterator)。
对于range、列表、元组、字符串、字典、集合等可迭代对象,多不能作为内置函数next()的实参,而生成器可以,所以,生成器是迭代器的一种、
可以调用内置函数isinstance()判断一个对象时候是迭代器对象,标准库模块collections中的类Iterator用于表示迭代器对象。

>>> from collections import Iterator
>>>
>>> isinstance([1, 2, 3], Iterator)
False
>>> isinstance([1, 2, 3], Iterable)
True

可以调用内置函数iter()把不支持惰性推算的可迭代对象转换为迭代器对象。

>>> isinstance(iter([1, 2, 3]), Iterator)
True
>>>
>>> iter([1, 2, 3])
<list_iterator object at 0x7f1970abf780>
>>>
>>> I = iter([1, 2, 3])
>>> I
<list_iterator object at 0x7f1970abf6d8>
>>>
>>> isinstance(I, Iterator)
True

>>> next(I)
1
>>> next(I)
2
>>> next(I)
3
>>> next(I)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

如果一个对象同时实现了特殊方法__iter__()__next__(),那么该对象也被称为迭代器对象。

类对象特殊方法——iter()、next()


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com