在同一函数中返回并产生

nek*_*imi 58 python yield

当在Python中的同一函数中使用yield和return时,究竟会发生什么?

def find_all(a_str, sub):
    start = 0
    while True:
        start = a_str.find(sub, start)
        if start == -1: return
        yield start
        start += len(sub) # use start += 1 to find overlapping matches
Run Code Online (Sandbox Code Playgroud)

它还是发电机吗?

NPE*_*NPE 62

是的,它仍然是一个发电机.的return(几乎),相当于提高StopIteration.

PEP 255说出来:

规格:退货

生成器函数还可以包含以下形式的return语句:

"return"
Run Code Online (Sandbox Code Playgroud)

请注意,生成器主体中的return语句不允许使用expression_list(当然,它们可能出现在嵌套在生成器中的非生成器函数的主体中).

遇到return语句时,控制继续执行任何函数返回,执行适当的finally子句(如果存在).然后引发StopIteration异常,表示迭代器已耗尽.如果控制流出生成器的末尾而没有显式返回,也会引发StopIteration异常.

请注意,对于生成器函数和非生成器函数,返回表示"我已完成,并且没有任何有趣的返回".

请注意,返回并不总是等同于提高StopIteration:区别在于如何处理封闭的try/except结构.例如,

>>> def f1():
...     try:
...         return
...     except:
...        yield 1
>>> print list(f1())
[]
Run Code Online (Sandbox Code Playgroud)

因为,就像在任何函数中一样,返回只是退出,但是

>>> def f2():
...     try:
...         raise StopIteration
...     except:
...         yield 42
>>> print list(f2())
[42]
Run Code Online (Sandbox Code Playgroud)

因为StopIteration是由一个简单的"除外"捕获的,就像任何异常一样.

  • @Zack在Python 2.x中,它是一个SyntaxError:`SyntaxError:'return',带有参数在generator`中.它在Python 3.x中是允许的,但主要用于与协同程序一起使用 - 你使用`yield coroutine()`或`来自coroutine()`来对其他协同程序进行异步调用,这取决于你的异步框架使用),并使用`return value`返回你想从协程返回的任何内容.在Python 2.x中,你需要使用诸如`raise Return(value)`之类的技巧来从协同程序返回值. (14认同)
  • 您知道“ return”有参数时会发生什么吗? (2认同)

Ash*_*ary 25

是的,它仍然是一个发电机.空returnreturn None可用于结束生成器功能.这相当于提高了StopIteration(详见@ NPE的答案).

请注意,带有非None参数的返回是SyntaxError3.3之前的Python版本.

正如@BrenBarn在从Python 3.3开始的评论中指出的那样,返回值现在传递给了 StopIteration.

PEP 380:

在发电机中,声明

return value
Run Code Online (Sandbox Code Playgroud)

在语义上等同于

raise StopIteration(value)
Run Code Online (Sandbox Code Playgroud)

  • 在Python 3.3及更高版本中,您可以使用带有参数的`return`将参数传递给引发的StopIteration.请参阅[此问题](http://stackoverflow.com/questions/16780002/return-in-generator-together-with-yield-in-python-3-3). (4认同)
  • @AshwiniChaudhary它启用了Python中的基本协同程序 - 能够将值/异常发送到生成器,并通过`value = yield`等接收它们."yield from"的引入和来自生成器的"返回"值的能力来自于[PEP 380](http://legacy.python.org/dev/peps/pep-0380/),两者都被`asyncio`利用.您仍然可以使用PEP 343提供的功能来实现强大的协程实现,编写它们只是不那么干净. (3认同)
  • 你知道如果 `return` 有一个参数(除了 `None`)会发生什么? (2认同)

Wil*_*ack 10

有一种方法可以在函数中实现yield和return方法,该函数允许您返回值或生成器.

它可能不像你想要的那么干净,但它确实做你期望的.

这是一个例子:

def six(how_many=None):
    if how_many is None or how_many < 1:
        return None  # returns value

    if how_many == 1:
        return 6  # returns value

    def iter_func():
        for count in range(how_many):
            yield 6
    return iter_func()  # returns generator
Run Code Online (Sandbox Code Playgroud)