在以下情况下使用生成器函数有哪些优点?

2024-09-26 22:12:56 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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()

解决方案如下:

^{pr2}$

两种情况下的输出相同:

codewingx@CodeLair:~/repo/python$ python load_balancer.py
APP1
APP2
APP3
APP1
APP2
APP3
APP1
APP2
APP3

那么,发电机的功能有什么好处呢?在


Tags: 元素目标列表getservercurrentlengthservers
2条回答

在这种情况下,列表是它自己的生成器:

for i in SERVERS:
    do_something_with_element(i)

如果你想要一个无限的发电机,@MikeMüller的itertools.cycle最好不要重新发明轮子。如果你必须自己动手:

^{pr2}$

但不要这样做,它效率较低,并且需要更多代码读取器的内存。在

使用itertools.cycle()

生成器在这里没有添加任何有用的内容。我会尽量避免pop(0),因为它每次都会触发整个服务器列表的重建。在

我建议itertools.cycle()

from __future__ import print_function

from itertools import cycle

SERVERS = ['APP1', 'APP2', 'APP3']

servers = cycle(SERVERS)

for i in range(9):
    print(next(servers))

输出:

^{pr2}$

我们包装在一个函数中以匹配您的用法:

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())

输出:

^{pr2}$

编写你自己的生成器函数

为了说明生成器的意义,利用其存储stet的能力的变体可能更有用:

def gen():
    index = 0
    end = len(SERVERS)
    while True:
        yield SERVERS[index]
        index += 1
        if index >= end:
            index = 0

虽然这很好地说明了您使用index的状态,但是使用以下方法可以更容易地实现相同的效果:

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

g = gen()

def get_server():
    return next(g)

这样可以避免修改SERVERS的列表。结果是一样的:

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

输出:

^{pr2}$

发电机的工作原理

一个简单的生成器函数:

>>> 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放在while True循环中可以生成一个无限的生成器。只要不调用close(),它就会给你一个带有yield的新值。另外,你在生成器中有状态。这意味着您可以在调用next()之间执行递增计数器之类的操作。在

相关问题 更多 >

    热门问题