生成器是惰性求值的,所以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 模块中找到更多帮助器。在这种简单的情况下,我会简单地求助于这些,并且仅在不平凡的情况下编写您自己的生成器。
但我认为您的真实代码更复杂,因此可能不适用,但我认为如果不提及替代方案,这将不是一个完整的答案。