一、迭代器
>>> 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)
...
>>>
>>> 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]
>>> l
[0, 1, 2, 3, 4]
三、生成器
1、
>>> l = (i for i in range(0,5))
>>> l
<generator object <genexpr> at 0x7fcab12ebe10>
>>> 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
... 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
...
... 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>
>>> 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
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所引用的这个生成器对象里面每东西了,生成器对象是惰性的,调用他他才会给你返回值。
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)
...
... print(i)
...
>>>
接下来探究yield究竟发生了什么事情--------------------------------------------------------------------------
接下来探究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
... 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,可以做控制。