在同一函数中返回并产生

时间:2014-10-27 20:04:28

标签: 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

它还是发电机吗?

4 个答案:

答案 0 :(得分:55)

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

PEP 255说出来:

  

规格:退货

     

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

"return"
     

请注意,返回语句中不允许使用expression_list   发电机的主体(当然,它们可能出现在发电机中)   嵌套在发电机内的非发电机功能体。)

     

当遇到return语句时,控制按任何方式进行   函数返回,执行适当的finally子句(如果有的话)   存在)。然后引发一个StopIteration异常,表示该异常   迭代器已经用尽了。如果是,也会引发StopIteration异常   控制流从发电机的末端流出而没有明确的返回。

     

请注意,返回意味着“我已经完成了,并没有任何有趣的东西   返回“,用于发电机功能和非发电机功能。

     

请注意,返回并不总是等同于提升StopIteration:   区别在于try / except结构的封闭程度   对待。例如,

>>> def f1():
...     try:
...         return
...     except:
...        yield 1
>>> print list(f1())
[]
     

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

>>> def f2():
...     try:
...         raise StopIteration
...     except:
...         yield 42
>>> print list(f2())
[42]
     

因为StopIteration是由一个裸的“except”捕获的,就像任何一样   异常。

答案 1 :(得分:24)

是的,它仍然是一台发电机。空returnreturn None可用于结束生成器函数。这相当于提高StopIteration(有关详细信息,请参阅@NPE's answer。)

请注意,在3.3之前的Python版本中,带有非None参数的返回值为SyntaxError

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

来自PEP 380

  

在生成器中,语句

return value
     

在语义上等同于

raise StopIteration(value)

答案 2 :(得分:8)

有一种方法可以在函数中实现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

答案 3 :(得分:0)

注意:以下示例不会导致StopIteration异常。

def odd(max):
    n = 0
    while n < max:
        yield n
        n = n + 1
    return 'done'


for x in odd(3):
    print(x)

for循环将其捕获。那是停止的信号

但是您可以通过以下方式捕获它:

g = odd(3)

while True:
    try:
        x = next(g)
        print(x)
    except StopIteration as e:
        print("g return value:", e.value)
        break