生成器带返回语句

时间:2016-06-06 15:19:29

标签: python generator

在我的报道中,我对以下案例(python 3.4)嗤之以鼻。

def simple_gen_function(str_in, sep=""):
    if sep == "":
        yield str_in[0]
        for c in str_in[1:]:
            yield c
    else:
        return str_in
        # yield from str_in

str_in = "je teste "
t = "".join(simple_gen_function(str_in))
p = "".join(simple_gen_function(str_in, "\n"))

print("%r %r" % (t, p))
# 'je teste' ''

在发电机中使用退货,退货未达到""使用yield from str_in时,我有预期的结果。

这个问题看起来很简单,但我相信在发电机中使用返回,它已经达到了。

1 个答案:

答案 0 :(得分:4)

函数体中yield的存在将其转换为生成函数而不是正常函数。在生成器函数中,使用return是一种说法“生成器已经结束,没有更多元素。”通过使生成器方法的第一个语句为return str_in,您可以保证生成器不返回任何元素。

正如评论所提到的,返回值用作生成器结束时引发的StopIteration异常的参数。参见:

>>> gen = simple_gen_function("hello", "foo")
>>> next(gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: hello

如果yield中有def,那就是发电机!

在评论中,提问者提到他们认为当执行yield语句时,函数会动态变为生成器。但这不是它的工作方式!在代码被执行之前做出决定。如果Python在yield下的任何地方找到def,则会将def转换为生成器函数。

看到这个超简洁的例子:

>>> def foo():
...     if False:
...         yield "bar"
...     return "baz"
>>> foo()
<generator object foo at ...>
>>> # The return value "baz" is only exposed via StopIteration
>>> # You probably shouldn't use this behavior.
>>> next(foo())
Traceback (most recent call last):
  ...
StopIteration: baz
>>> # Nothing is ever yielded from the generator, so it generates no values.
>>> list(foo())
[]