4,837次阅读

# 迭代器简介

## 迭代器初级应用

<span class="prompt">>>> </span>L = [x * x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>)]
<span class="prompt">>>> </span>L
[<span class="number">0</span>, <span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>, <span class="number">16</span>, <span class="number">25</span>, <span class="number">36</span>, <span class="number">49</span>, <span class="number">64</span>, <span class="number">81</span>]
<span class="prompt">>>> </span>g = (x * x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>))
<span class="prompt">>>> </span>g
<generator object <genexpr> at <span class="number">0x1022ef630</span>>


>>> <span class="keyword">next</span>(g)
<span class="number">0</span>
>>> <span class="keyword">next</span>(g)
<span class="number">1</span>
>>> <span class="keyword">next</span>(g)
<span class="number">4</span>
>>> <span class="keyword">next</span>(g)
<span class="number">9</span>
>>> <span class="keyword">next</span>(g)
<span class="number">16</span>
>>> <span class="keyword">next</span>(g)
<span class="number">25</span>
>>> <span class="keyword">next</span>(g)
<span class="number">36</span>
>>> <span class="keyword">next</span>(g)
<span class="number">49</span>
>>> <span class="keyword">next</span>(g)
<span class="number">64</span>
>>> <span class="keyword">next</span>(g)
<span class="number">81</span>
>>> <span class="keyword">next</span>(g)
<span class="constant">Traceback</span> (most recent call last)<span class="symbol">:</span>
<span class="constant">File</span> <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <<span class="keyword">module</span>>
<span class="constant">StopIteration</span>


<span class="prompt">>>> </span>g = (x * x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>))
<span class="prompt">>>> </span><span class="keyword">for</span> n <span class="keyword">in</span> g:
<span class="prompt">... </span>    print(n)
<span class="prompt">... </span>
<span class="number">0</span>
<span class="number">1</span>
<span class="number">4</span>
<span class="number">9</span>
<span class="number">16</span>
<span class="number">25</span>
<span class="number">36</span>
<span class="number">49</span>
<span class="number">64</span>
<span class="number">81</span>


generator非常强大。如果推算的算法比较复杂，用类似列表生成式的for循环无法实现的时候，还可以用函数来实现。

1, 1, 2, 3, 5, 8, 13, 21, 34, …

<span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(max)</span>:</span>
n, a, b = <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>
<span class="keyword">while</span> n < max:
print(b)
a, b = b, a + b
n = n + <span class="number">1</span>
<span class="keyword">return</span> <span class="string">'done'</span>


<span class="prompt">>>> </span>fib(<span class="number">6</span>)
<span class="number">1</span>
<span class="number">1</span>
<span class="number">2</span>
<span class="number">3</span>
<span class="number">5</span>
<span class="number">8</span>
<span class="string">'done'</span>


<span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(max)</span>:</span>
n, a, b = <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>
<span class="keyword">while</span> n < max:
<span class="keyword">yield</span> b
a, b = b, a + b
n = n + <span class="number">1</span>
<span class="keyword">return</span> <span class="string">'done'</span>


yield可以理解为return，对于yield之后的表达式返回，次也会保留现场的变量信息，如果存在

 m=<span class="keyword">yield</span> b

>>> f = fib(6)
>>> f
<span class="tag"><<span class="title">generator</span> <span class="attribute">object</span> <span class="attribute">fib</span> <span class="attribute">at</span> <span class="attribute">0x104feaaa0</span>></span>


<span class="function"><span class="keyword">def</span> <span class="title">odd</span><span class="params">()</span>:</span>
print(<span class="string">'step 1'</span>)
<span class="keyword">yield</span> <span class="number">1</span>
print(<span class="string">'step 2'</span>)
<span class="keyword">yield</span>(<span class="number">3</span>)
print(<span class="string">'step 3'</span>)
<span class="keyword">yield</span>(<span class="number">5</span>)


>>> o = odd()
>>> <span class="keyword">next</span>(o)
step <span class="number">1</span>
<span class="number">1</span>
>>> <span class="keyword">next</span>(o)
step <span class="number">2</span>
<span class="number">3</span>
>>> <span class="keyword">next</span>(o)
step <span class="number">3</span>
<span class="number">5</span>
>>> <span class="keyword">next</span>(o)
<span class="constant">Traceback</span> (most recent call last)<span class="symbol">:</span>
<span class="constant">File</span> <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <<span class="keyword">module</span>>
<span class="constant">StopIteration</span>


<span class="prompt">>>> </span><span class="keyword">for</span> n <span class="keyword">in</span> fib(<span class="number">6</span>):
<span class="prompt">... </span>    print(n)
...
<span class="number">1</span>
<span class="number">1</span>
<span class="number">2</span>
<span class="number">3</span>
<span class="number">5</span>
<span class="number">8</span>


<span class="prompt">>>> </span>g = fib(<span class="number">6</span>)
<span class="prompt">>>> </span><span class="keyword">while</span> <span class="built_in">True</span>:
<span class="prompt">... </span>    <span class="keyword">try</span>:
<span class="prompt">... </span>        x = next(g)
<span class="prompt">... </span>        print(<span class="string">'g:'</span>, x)
<span class="prompt">... </span>    <span class="keyword">except</span> StopIteration <span class="keyword">as</span> e:
<span class="prompt">... </span>        print(<span class="string">'Generator return value:'</span>, e.value)
<span class="prompt">... </span>        <span class="keyword">break</span>
...
g: <span class="number">1</span>
g: <span class="number">1</span>
g: <span class="number">2</span>
g: <span class="number">3</span>
g: <span class="number">5</span>
g: <span class="number">8</span>
Generator <span class="keyword">return</span> value: done

## 迭代器协程应用

<span class="function"><span class="keyword">def</span> <span class="title">consumer</span><span class="params">()</span>:</span>
r = <span class="string">''</span>
<span class="keyword">while</span> <span class="built_in">True</span>:
n = <span class="keyword">yield</span> r
<span class="keyword">if</span> <span class="keyword">not</span> n:
<span class="keyword">return</span>
print(<span class="string">'[CONSUMER] Consuming %s...'</span> % n)
r = <span class="string">'200 OK'</span>

<span class="function"><span class="keyword">def</span> <span class="title">produce</span><span class="params">(c)</span>:</span>
c.send(<span class="built_in">None</span>)
n = <span class="number">0</span>
<span class="keyword">while</span> n < <span class="number">5</span>:
n = n + <span class="number">1</span>
print(<span class="string">'[PRODUCER] Producing %s...'</span> % n)
r = c.send(n)
print(<span class="string">'[PRODUCER] Consumer return: %s'</span> % r)
c.close()

c = consumer()
produce(c)

#在c=consumer()运行之后得到的只是一个迭代器初始化过程，此时consumer函数本身并没有运行
#也就是说下面这个函数#1这句代码都没有运行
<span class="function"><span class="keyword">#def</span> <span class="title">consumer</span><span class="params">()</span>:</span>
#   r = <span class="string">''            #1 </span>
#   <span class="keyword">while</span> <span class="built_in">True</span>:       #2
#       n = <span class="keyword">yield</span> r   #3
#       <span class="keyword">if</span> <span class="keyword">not</span> n:     #4
#          <span class="keyword">return     #5</span>
#       print(<span class="string">'[CONSUMER] Consuming %s...'</span> % n)     #6
#       r = <span class="string">'200 OK'   #7
#上面的代码中存在c.send(None)，这个代码的作用就是
c.send(<span class="built_in">None</span>)
#上述代码的等效于
c.next()
#此时开始获取迭代器中的值，此时会有疑问，为什么不可以发送其他值？首先迭代器没有运行，你就尝试给它发送消息，它
#也不知道怎么处理，因此就会报错，因此必须先发送None

</span>

for  i in  consumer():
print(i);
#注意到这个跟上面描述的情况就是不太一样了，此时并没有send(None)还有next()的代码
#但是你要知道for循环中会自动调用next函数的，所以就不用我们担心这个问题了

flyking博客