hya*_*kov 31 python yield return function generator
我有一个生成器generator
和一个方便的方法 - generate_all
。
def generator(some_list):
for i in some_list:
yield do_something(i)
def generate_all():
some_list = get_the_list()
return generator(some_list) # <-- Is this supposed to be return or yield?
Run Code Online (Sandbox Code Playgroud)
应该generate_all
return
还是yield
?我希望两种方法的用户都使用相同的方法,即
for x in generate_all()
Run Code Online (Sandbox Code Playgroud)
应该等于
some_list = get_the_list()
for x in generate(some_list)
Run Code Online (Sandbox Code Playgroud)
ti7*_*ti7 18
您可能正在寻找生成器委托 (PEP380)
对于简单的迭代器,
yield from iterable
本质上只是一种缩写形式for item in iterable: yield item
def generator(iterable):
for i in iterable:
yield do_something(i)
def generate_all():
yield from generator(get_the_list())
Run Code Online (Sandbox Code Playgroud)
它非常简洁,还有许多其他优点,例如能够链接任意/不同的迭代!
che*_*ner 15
return generator(list)
做你想做的。但请注意
yield from generator(list)
Run Code Online (Sandbox Code Playgroud)
将是等效的,但有机会在generator
用尽后产生更多值。例如:
def generator_all_and_then_some():
list = get_the_list()
yield from generator(list)
yield "one last thing"
Run Code Online (Sandbox Code Playgroud)
MSe*_*ert 13
发电机是懒惰的,所以评估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():
...
Run Code Online (Sandbox Code Playgroud)
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():
...
Run Code Online (Sandbox Code Playgroud)
如果它使用yield from
:
def generate_all():
some_list = [1,2,3]
yield from generator(some_list)
for item in generate_all():
...
Run Code Online (Sandbox Code Playgroud)
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 :-)
Run Code Online (Sandbox Code Playgroud)
然而,这是以性能为代价的。额外的生成器层确实有一些开销。所以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)
Run Code Online (Sandbox Code Playgroud)
def generate_all():
some_list = [1,2,3]
yield from generator(some_list)
for item in generate_all():
...
Run Code Online (Sandbox Code Playgroud)
在您的情况下,操作非常简单,我不知道是否有必要为此创建多个函数,您可以轻松地使用内置map
表达式或生成器表达式:
map(do_something, get_the_list()) # map
(do_something(i) for i in get_the_list()) # generator expression
Run Code Online (Sandbox Code Playgroud)
两者应该是相同的(除了发生异常时的一些差异)才能使用。如果他们需要一个更具描述性的名称,那么您仍然可以将它们包装在一个函数中。
有多个助手可以在内置的可迭代对象上包装非常常见的操作,更多的可以在内置itertools
模块中找到。在这种简单的情况下,我只会求助于这些,并且仅在非平凡的情况下编写您自己的生成器。
但我认为您的真实代码更复杂,因此可能不适用,但我认为如果不提及替代方案,它就不会是一个完整的答案。
Mad*_*ist 10
在这种特殊情况下,以下两个语句在功能上是等效的:
return generator(list)
Run Code Online (Sandbox Code Playgroud)
和
yield from generator(list)
Run Code Online (Sandbox Code Playgroud)
后者大致相同
for i in generator(list):
yield i
Run Code Online (Sandbox Code Playgroud)
该return
语句返回您正在寻找的生成器。一个yield from
或yield
声明将你的整体功能到的东西,返回一个生成器,它通过你正在寻找的人。
从用户的角度来看,没有区别。然而,在内部,return
它可以说更有效,因为它没有包含generator(list)
在一个多余的直通发生器中。如果您打算对包装生成器的元素进行任何处理yield
,当然可以使用某种形式。
归档时间: |
|
查看次数: |
1979 次 |
最近记录: |