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我很难理解这个新概念。我只是在学习,这是一个有趣的概念。意识到一个列表可能有很多数据,这就带来了虚拟列表的真正用途。找到更好的教程。