python 生成器和迭代器

一、迭代器

>>> a = iter([1,2,3,4,5])   ---翻译:在内存中创建了一个迭代器对象,a是对其的引用
>>> type(a)
<type 'listiterator'>
>>> a
<listiterator object at 0x7fcab12a6810>
>>> for i in a:             ---迭代第一次
...     print(i)
...
1
2
3
4
5
>>> for i in a:           ---只能迭代一次
...     print(i)
...
>>>

二、列表生成式

 生成一个列表

>>> l = [i for i in range(0,5)]
>>> l
[0, 1, 2, 3, 4]

三、生成器

1、

>>> l = (i for i in range(0,5))
>>> l
<generator object <genexpr> at 0x7fcab12ebe10>
>>> for i in l:
...     print(i)
...
0
1
2
3
4
>>> for i in l:
...     print(i)
...
>>> l.next()    
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration        ----到了stopiteration

2、yield

>>> def test(i):
...     while i<6:
...             yield i
...             i = i+1
...
>> test                     ----函数对象
<function test at 0x7fcab12a85f0>
>>> test()                   ----函数调用,返回生成器对象
<generator object test at 0x7fcab12ebe10>
>>> a = test(x)         ---调用函数,函数里代码并没有执行,函数仅仅返回生成器对象
>>> a
<generator object test1 at 0x7fcab12ebe10>
>>> test(x).next()       ----为什么每次调用,都是111,不应该是123吗?是因为每次都是一次重新调用,返回的都是一个新的生成器对象,所以都是1
1
>>> test(x).next()
1

>>> test(x).next()
1
>>> a.next()           ----直接在a的基础上next就大不一样咯!!因为同一个生成器对象
1
>>> a.next()
2
>>> a.next()
3
>>> a.next()
4
>>> a.next()
5
>>> a.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration               -----------停止迭代了,a所引用的这个生成器对象里面每东西了,生成器对象是惰性的,调用他他才会给你返回值。
>>> for i in a:
...     print(i)
...
>>>
接下来探究yield究竟发生了什么事情--------------------------------------------------------------------------
>>> b=test(x)         ------创建一个生成器对象b ,此时函数里的代码并没有运转

>>> for i in b:       ------for第一次做迭代的时候,函数代码开始运转,直到遇到yield,返回第一个值,第二次循环从yield下一个语句开始,直到再一次遇到yield,一直到i=6,跳过while,此时遇不到yield,认为生成器已经空了,返回StopIteration。以后当然也迭代不了 
...     print(i)
...
1
2
3
4
5

这个是stackoverflow里的问题,值得一看: http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python

这是中文版: http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html

这篇文章深入浅出 https://www.cnblogs.com/deeper/p/7565571.html

四、简单小结

迭代器也好,生成器也好,都是惰性的,因此可以节约大量内存空间。举个例子,一亿个元素的列表放在内存就炸了,但是如果是一个生成器对象,我们用的时候做一个循环,取到我们需要的元素,而且在循环的时候,遵循这样一个过程:计算第一个数,然后内存中丢了,再算下一个数,直到最后。这样大大节省了内存空间。当然用完到StopIteration就没了,只能一次迭代。

迭代器和生成器有什么区别呢?

1、生成器是特殊的迭代器,生成器一定是迭代器,迭代器不一定是生成器。

2、生成器很优雅,不需要迭代器中再定义iter,next,一个关键字yield就ok

3、生成器可以做send,可以做控制。


猜你喜欢

转载自www.cnblogs.com/mengmengzhang/p/9693193.html