发电机是懒惰的,所以评估return
或yield
将表现不同,当你调试代码,或者抛出一个异常。
不管return
发生什么异常,您generator
一无所知generate_all
,这是因为在generator
真正执行时,您已经离开了该generate_all
功能。随着yield
在那里它会generate_all
在回溯。
def generator(some_list):
for i in some_list:
raise Exception('exception happened :-)')
yield i
def generate_all():
some_list = [1,2,3]
return generator(some_list)
for item in generate_all():
...
Exception Traceback (most recent call last)
<ipython-input-3-b19085eab3e1> in <module>
8 return generator(some_list)
9
---> 10 for item in generate_all():
11 ...
<ipython-input-3-b19085eab3e1> in generator(some_list)
1 def generator(some_list):
2 for i in some_list:
----> 3 raise Exception('exception happened :-)')
4 yield i
5
Exception: exception happened :-)
如果正在使用yield from
:
def generate_all():
some_list = [1,2,3]
yield from generator(some_list)
for item in generate_all():
...
Exception Traceback (most recent call last)
<ipython-input-4-be322887df35> in <module>
8 yield from generator(some_list)
9
---> 10 for item in generate_all():
11 ...
<ipython-input-4-be322887df35> in generate_all()
6 def generate_all():
7 some_list = [1,2,3]
----> 8 yield from generator(some_list)
9
10 for item in generate_all():
<ipython-input-4-be322887df35> in generator(some_list)
1 def generator(some_list):
2 for i in some_list:
----> 3 raise Exception('exception happened :-)')
4 yield i
5
Exception: exception happened :-)
但是,这是以性能为代价的。附加的生成器层确实有一些开销。因此return
通常会比yield from ...
(或for item in ...: yield item
)快一点。在大多数情况下,这无关紧要,因为您在生成器中所做的任何事情通常都会影响运行时,因此额外的层将不会很明显。
但是,它yield
还有一些其他优点:您不仅限于单个可迭代对象,还可以轻松产生其他项:
def generator(some_list):
for i in some_list:
yield i
def generate_all():
some_list = [1,2,3]
yield 'start'
yield from generator(some_list)
yield 'end'
for item in generate_all():
print(item)
start
1
2
3
end
在您的情况下,操作非常简单,并且我不知道是否为此需要创建多个函数,可以轻松地使用内置函数map
或生成器表达式来代替:
map(do_something, get_the_list()) # map
(do_something(i) for i in get_the_list()) # generator expression
两者应相同(除了发生异常时的一些区别)使用。而且,如果它们需要一个更具描述性的名称,那么您仍然可以将它们包装在一个函数中。
有多个帮助程序将非常常见的操作包装在内置的可迭代对象上,进一步的操作可以在内置itertools
模块中找到。在这种简单的情况下,我仅会求助于这些情况,并且仅在非平凡的情况下编写您自己的生成器。
但是我认为您的实际代码更加复杂,因此可能不适用,但我认为如果不提及替代方案,这将不是一个完整的答案。