Python 在以下情况下使用生成器功能的优点是什么?

Python 在以下情况下使用生成器功能的优点是什么?,python,python-2.7,generator,Python,Python 2.7,Generator,我的任务的目标是无限期地生成列表元素。 所以我这样做了: SERVERS = ['APP1', 'APP2', 'APP3'] #SERVERS = ['APP1', 'APP2', 'APP3', 'APP4', 'APP5', 'APP6'] length = len(SERVERS) def get_server(): current_server = SERVERS.pop(0) SERVERS.append(current_server) return cur

我的任务的目标是无限期地生成列表元素。 所以我这样做了:

SERVERS = ['APP1', 'APP2', 'APP3']
#SERVERS = ['APP1', 'APP2', 'APP3', 'APP4', 'APP5', 'APP6']
length = len(SERVERS)

def get_server():
    current_server = SERVERS.pop(0)
    SERVERS.append(current_server)
    return current_server

if __name__ == '__main__':
    for i in range(9):
        print get_server()
解决方案有如下内容:

SERVERS = ['APP1', 'APP2', 'APP3']
#SERVERS = ['APP1', 'APP2', 'APP3', 'APP4', 'APP5', 'APP6']

def get_server():
    def f():
        while True:
            i = SERVERS.pop(0)
            SERVERS.append(i)
            yield i
    return next(f())

if __name__ == '__main__':
    for i in range(9):
        print get_server()
尽管两种情况下的输出相同:

codewingx@CodeLair:~/repo/python$ python load_balancer.py
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
那么,生成器函数有什么好处呢?

使用
itertools.cycle()
生成器没有在此处添加任何有用的内容。我会尽量避免弹出(0),因为它每次都会触发整个服务器列表的重建

我建议:

输出:

APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
我们的产品包装在一个函数中,以匹配您的使用:

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())
输出:

APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
编写自己的生成器函数 为了说明生成器的重要性,利用其存储stet能力的变体可能更有用:

def gen():
    index = 0
    end = len(SERVERS)
    while True:
        yield SERVERS[index]
        index += 1
        if index >= end:
            index = 0
虽然这很好地说明了您可以使用
索引
,但使用以下工具可以更轻松地实现这一点:

def gen():
    while True:
        for server in SERVERS:
            yield server

g = gen()

def get_server():
    return next(g)
这样可以避免修改
服务器的列表。结果是一样的:

for i in range(9):
    print(get_server())
输出:

APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3
发电机的工作原理 一个简单的生成器函数:

>>> def gen():
...     print('start')
...     yield 1
...     print('after 1')
...     yield 2
...     print('after 2')
...
举例说明:

>>> g = gen()
使用
next
获取
yield
返回的下一个值:

>>> next(g)
start
1
继续:

>>> next(g)
after 1
2
现在它已经精疲力竭了:

>>> next(g)
after 2

StopIteration  next(g)

您可能会想到在生成器函数中移动的光标。每次调用
next()
时,它都会移动到下一个
yield
。因此,将
yield
放在
中,而True
循环会生成一个无限的生成器。只要你不调用它的
close()
,它就会给你一个新的
yield
值。此外,在生成器中还有状态。这意味着您可以在调用
next()

之间增加计数器。在此上下文中,列表是它自己的生成器:

for i in SERVERS:
    do_something_with_element(i)
如果你想要一个无限的发电机,@MikeMüller的
itertools.cycle
是最好的选择,因为它不需要重新发明轮子。如果您必须自己做:

def my_cycle(s):
    while True:
        for i in s:
             yield i

但是不要这样做,这样效率会降低,并且会占用代码读取器更多的内存。

我仍在努力理解一个收益率。文档中说,收益率是指当再次调用函数时,执行停止并从此时开始恢复的点。我喜欢“创建您自己的生成器”方法。@AmreshVenugopal我喜欢将生成器作为一个虚拟列表,包含它生成的所有内容,但与列表不同,它有自己的语法,只能一次使用,可以有无穷多个元素,但在您要求之前,它没有任何元素,在那一刻,生成器一直执行到第一个屈服点,并一直保持在那里,直到您请求下一个元素,它一直执行到下一个屈服点,依此类推on@MikeMüller,你的编辑对理解很有帮助。我现在完全明白了产量和下一步与发电机的关系。我很高兴这对我有所帮助。@Copperfield我很难理解这个新概念。我只是在学习,这是一个有趣的概念。意识到一个列表可能有很多数据,这就带来了虚拟列表的真正用途。找到更好的教程。