Python生成器的等价于`return`的语句

3
有时候,当将递归函数改写成生成器时,我会感到缺少return的简洁性。
"""
Returns a list of all length n strings that can be made out of a's and/or b's.
"""
def ab_star(n):
    if n == 0:
        return [""]

    results = []
    for s in ab_star(n - 1):
        results.append("a" + s)
        results.append("b" + s)

    return results

转化为
"""
Generator for all length n strings that can be made out of a's and/or b's.
"""
def ab_star(n):
    if n == 0:
        yield ""

    else:
        for s in ab_star(n - 1):
            yield "a" + s
            yield "b" + s

让我感到困扰的是那个 else。我希望有一种方法能够说:“yield,这就是它,退出函数”。是否有一种方法呢?


为什么第一次使用 yield 后不加一个 return 呢? - anon582847382
2个回答

7

不要错过return,要善加利用。

在使用yield后,你可以立即使用return

def ab_star(n):
    if n == 0:
        yield ""
        return
    for s in ab_star(n - 1):
        yield "a" + s
        yield "b" + s

另一种方法是在两种情况下都使用return,其中第一种情况返回长度为1的序列,第二种情况返回一个生成器表达式。
def ab_star(n):
    if n == 0:
        return ( "", )
    return ( c+s for s in ab_star(n - 1) for c in 'ab' )

避免使用 yield 可以避免在同一个函数中无法同时使用 return <value>yield 的限制。
(这在您的情况下有效,因为您的函数不一定是生成器。由于您只迭代结果,它还可以返回元组。)

5

没有。当我写“简单生成器PEP”时,我指出:

Q. Then why not allow an expression on "return" too?

A. Perhaps we will someday.  In Icon, "return expr" means both "I'm
   done", and "but I have one final useful value to return too, and
   this is it".  At the start, and in the absence of compelling uses
   for "return expr", it's simply cleaner to use "yield" exclusively
   for delivering values.

但这从未引起关注。直到它能够被实现为止,你可以通过以下方式将你的生成器看起来更像第一个函数:

if n == 0:
    yield ""
    return

然后您可以删除else:语句并缩进其余部分。

哦,有趣。从这个答案来看,return <expr>现在实际上意味着不同的东西了。所以我猜这永远不会发生? - Eli Rose
是的,在3.3版本中,生成器内的return <expr>语句获得了一种含义,但这种含义与产生值无关,相当晦涩。相反,它与StopIteration异常有关,正如您链接到的答案所指出的那样。 - Tim Peters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接