Python高级特性(三)

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 100 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。在 Python 中,
这种一边循环一边计算的机制,称为生成器:generator。要创建一个 generator,有很多种方法。
1.只要把一个列表生成式的[]改成(),就创建了一个 generator:

>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x000001B40FE254F8>

然后我们需要调用next()方法对生成器生成的列表进行输出:

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<pyshell#63>", line 1, in <module>
    next(g)
StopIteration

generator 保存的是算法,每次调用 next(g),就计算出 g 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration 的错误。

>>> g = (x * x for x in range(1,10))
>>> for x in g:
	print(x)
1
4
9
16
25
36
49
64
81

所以,我们创建了一个 generator 后,基本上永远不会调用 next(),而是
通过 for 循环来迭代它,并且不需要关心 StopIteration 的错误.
2.如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个 generator:

>>> def odd():
	print('step 1')
	yield 1
	print('step 2')
	yield(3)
	print('step 3')
	yield(5)

	      
>>> o = odd()
	      
>>> next(o)
	      
step 1
1
>>> next(o)
	      
step 2
3
>>> next(o)
	      
step 3
5

迭代器

为什么 list、dict、str 等数据类型不是 Iterator?这是因为 Python 的 Iterator 对象表示的是一个数据流,Iterator 对象可以被 next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration 错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过 next()函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时
它才会计算。Iterator 甚至可以表示一个无限大的数据流,例如全体自然数。而使用list 是永远不可能存储全体自然数的。集合数据类型如 list、dict、str 等是 Iterable 但不是 Iterator,不过可以通过 iter()函数获得一个 Iterator 对象。
Python 的 for 循环本质上就是通过不断调用 next()函数实现的,例如:

for x in [1, 2, 3, 4, 5]:
 pass

实际上完全等价于:

it = iter([1, 2, 3, 4, 5])
发布了37 篇原创文章 · 获赞 42 · 访问量 4510

猜你喜欢

转载自blog.csdn.net/qq_43337175/article/details/104358622