<h2>使用<code>itertools.cycle()</code></h2>
<p>生成器在这里没有添加任何有用的内容。我会尽量避免<code>pop(0)</code>,因为它每次都会触发整个服务器列表的重建。在</p>
<p>我建议<a href="https://docs.python.org/3/library/itertools.html?highlight=cycle#itertools.cycle" rel="nofollow">itertools.cycle()</a>:</p>
<pre><code>from __future__ import print_function
from itertools import cycle
SERVERS = ['APP1', 'APP2', 'APP3']
servers = cycle(SERVERS)
for i in range(9):
print(next(servers))
</code></pre>
<p>输出:</p>
^{pr2}$
<p>我们包装在一个函数中以匹配您的用法:</p>
<pre><code>def make_get_server():
servers = cycle(SERVERS)
def get_server():
return next(servers)
return get_server
get_server = make_get_server()
for i in range(9):
print(get_server())
</code></pre>
<p>输出:</p>
^{pr2}$
<h2>编写你自己的生成器函数</h2>
<p>为了说明生成器的意义,利用其存储stet的能力的变体可能更有用:</p>
<pre><code>def gen():
index = 0
end = len(SERVERS)
while True:
yield SERVERS[index]
index += 1
if index >= end:
index = 0
</code></pre>
<p>虽然这很好地说明了您使用<code>index</code>的状态,但是使用以下方法可以更容易地实现相同的效果:</p>
<pre><code>def gen():
while True:
for server in SERVERS:
yield server
g = gen()
def get_server():
return next(g)
</code></pre>
<p>这样可以避免修改<code>SERVERS</code>的列表。结果是一样的:</p>
<pre><code>for i in range(9):
print(get_server())
</code></pre>
<p>输出:</p>
^{pr2}$
<h2>发电机的工作原理</h2>
<p>一个简单的生成器函数:</p>
<pre><code>>>> def gen():
... print('start')
... yield 1
... print('after 1')
... yield 2
... print('after 2')
...
</code></pre>
<p>举个例子:</p>
<pre><code>>>> g = gen()
</code></pre>
<p>使用<code>next</code>获得<code>yield</code>返回的下一个值:</p>
<pre><code>>>> next(g)
start
1
</code></pre>
<p>继续前进:</p>
<pre><code>>>> next(g)
after 1
2
</code></pre>
<p>现在它已经耗尽了:</p>
<pre><code>>>> next(g)
after 2
StopIteration next(g)
</code></pre>
<p>您可能会想到在生成器函数中移动的光标。每次调用<code>next()</code>时,它都会移动到下一个<code>yield</code>。因此,将<code>yield</code>放在<code>while True</code>循环中可以生成一个无限的生成器。只要不调用<code>close()</code>,它就会给你一个带有<code>yield</code>的新值。另外,你在生成器中有状态。这意味着您可以在调用<code>next()</code>之间执行递增计数器之类的操作。在</p>